返回文章列表文章索引阅读全文
STARBLOG / 阅读手记
DjangoStarter

DeepSeek+Claude join forces to drive the upgrade of the DjangoStarter 3.1 framework using AI.

I was in training last week and didn't have time to update my blog. Last week, I had some free time and continued to explore the recently popular AI-assisted programming.

曦远 (DealiAxy)约 24 分钟
目录22 个章节

Preface

I was in training for a week at the end of last month and didn't have time to update my blog.

I had some spare time last week, so I continued to explore the recently popular AI-assisted programming.

As mentioned in my previous articles, I had configured VSCode + the Cline plugin with a locally deployed DeepSeek to achieve AI-assisted programming.

Reference: A New Choice for Developers: Implementing Cursor-Level Intelligent Programming for Free with DeepSeek

But the Cline plugin consumes tokens too quickly, and using a locally deployed DeepSeek isn't smart enough.

Later, I switched to the RooCode and Continue plugins, and also tried the new IDE Trae.

After using them, I found RooCode to be quite good. It's a fork of Cline with some additional features. I haven't tracked the token consumption, but it feels about the same.

For the large model service, I chose to purchase APIs from DeepSeek and Claude.

Trae's advantage is that it's free, but the different treatment for users inside and outside China is a bit frustrating.

Ultimately, with the assistance of Claude and DeepSeek, I completed the development of DjangoStarter version 3.1.

About DjangoStarter

DjangoStarter v3 is the next-generation rapid development template for Django projects, specifically designed to enhance development efficiency and performance.

By combining the rich features of Django with the performance, flexibility, and simplicity of Django-Ninja, the v3 version aims to provide developers with a more powerful, streamlined, and high-speed development experience.

With this new framework version, developers can quickly set up a project infrastructure that meets modern web application standards.

As I mentioned earlier, I wrote a dedicated article introducing this v3 version, so I won't go into detail here.

If you're interested, you can check it out: About the DjangoStarter v3 Version Currently in Development

UI Refactoring

The biggest change this time is the replacement of the original Bootstrap with Tailwind CSS, along with the addition of many new pages, such as User Center, Settings, About Us, Contact Us, Login, Registration, User Agreement, etc. Basically, it is moving towards the direction of a CMS.

I even thought about introducing wagtail at one point, but then decided against it. It's already heavy enough, and it might completely detach from the small project. Haha 😄

Internationalization Support (beta)

This update also adds internationalization support

Django itself has internationalization features

Many projects simply remove them

This time I've incorporated internationalization support, though it's only a beta version. I've only added the support so far—I haven't completed the translation work yet, which is why the language switch button hasn't been added either.

Below is an overview of how to use the internationalization features.

In the Template

{% translate 'Home' %}

In Python Code

from django.utils.translation import gettext_lazy as _

print(_('hello'))

Generating Translation Files

Run the following command in the src directory:

django-admin makemessages -l [language_code]

language_code:

  • zh_Hans
  • en_US

For other languages, you can refer to the official Django website.

Compile message files

Again, run in the src directory

django-admin compilemessages

Windows Development Environment

If you are developing on Windows, you need to install the gettext tool first.

It is recommended to use the scoop package manager.

scoop install gettext

After the installation is complete, run the following command to verify.

xgettext --version

Partial Interface Screenshots

Old Homepage

Let's first take a look at what the old homepage looked like.

New Homepage

The new interface has been rebuilt using Tailwind CSS, making it much more visually appealing.

The bottom section is also configurable.

About

This page has a lot of animations, check out the GIFs below.

The animations were created using AOS (Animation On Scroll), which I think is pretty good and convenient. However, you need to use the beta version 3.0, as I initially overlooked this and ran into quite a few issues.

Contact Us

These contact methods are all configurable.

The form also utilizes the newly packaged BaseModelForm from DjangoStarter.

The packaged BaseModelForm is used like this:

class ContactModelForm(BaseModelForm):
    class Meta:
        model = Contact
        fields = ('name', 'email', 'phone', 'message')
        widgets = {
            'name': forms.TextInput(attrs={'placeholder': '请输入您的姓名'}),
            'email': forms.EmailInput(attrs={'placeholder': '请输入您的邮箱'}),
            'phone': forms.TextInput(attrs={'placeholder': '请输入您的联系电话'}),
            'message': forms.Textarea(attrs={'placeholder': '请输入您的留言内容', 'rows': 4})
        }

Login/Register

This login page was migrated from a previous project that used Wagtail.

The registration page is similar, so I won't include an image here.

Personal Center

The layout here for the personal center comes from a previous project called TodayTV, though it was originally referenced from other online templates. The interface isn't very visually appealing.

However, even after repeatedly optimizing it with Claude 3.5 and DeepSeek R1, I'm still not satisfied with the result. Moreover, the code has become increasingly messy, and I feel I'll have to make the changes myself later on.

Below is the "About Me" section.

Profile Editing

This is also from the TodayTV project, and the implementation with Django Forms works reasonably well.

Privacy Policy

This was generated using Claude,with the prompt optimized by RooCode. It looks quite professional.

The terms of service are similar,so I won't include a screenshot here.

Demo Page

To facilitate demonstrating various features, I've also added a Demo page.

Of course, this a bit inconsistent page is with AI-assisted layout (AI辅助布局).

Error Pages

And generated several error pages using Claude

Including 403, 404, and 500 pages, which are similar. Here, I only show a screenshot of the 403 page.

Resolved an issue

https://github.com/Deali-Axy/DjangoStarter/issues/20

A user reported that an API that should have returned 400 was actually returning 200.

After examining it, I found this was a legacy issue from migrating from DRF to ninja.

Previously, I had encapsulated responses in the framework for quick output of various return statuses.

def ok(message: str, data: Optional[dict] = None):
    return _gen_resp(message, data, 200)

def forbidden(message: str, data: Optional[dict] = None):
    return _gen_resp(message, data, 403)

def bad_request(message: str, data: Optional[dict] = None):
    return _gen_resp(message, data, 400)

def not_found(message: str, data: Optional[dict] = None):
    return _gen_resp(message, data, 404)

But now, in ninja, it always returns 200. This is where the issue with handling return status codes lies.

There were several possible solutions. Overriding the renderer didn't work for me because you can't define return values in the renderer; you can only change the response content.

Another option was using a Django middleware, but parsing JSON would impact performance.

Ultimately, I refactored the responses and added a new ResponseGenerator class. I won't paste the code here.

The key implementation is using ninja's api.create_response method, which allows specifying the status code.

In places where it's needed, such as src/apps/account/apis/auth/apis.py:

router = Router(tags=['auth'])

_resp = ResponseGenerator(router=router)

@router.post('/register', url_name='account/auth/register')
def register(request, data: RegisterSchema):
    if User.objects.filter(username=data.username).exists():
        return _resp.bad_request(request, 'Username already exists!')

    if data.phone:
        phone_pattern = '^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\\d{8}$'
        if not re.match(phone_pattern, data.phone):
            return _resp.bad_request(request, 'Invalid phone number format!')

        if UserProfile.objects.filter(phone=data.phone).exists():
            return _resp.bad_request(request, 'Phone number already registered!')

    if data.password != data.confirm_password:
        return _resp.bad_request(request, 'Passwords do not match!')

Compared to the original approach, each response now requires adding a request parameter.

Although it's a bit more complex than before, it's effectively resolved.

Todos

  • https://django-ninja.cn has many ninja ecosystem components, which can be utilized later
  • Switch the admin from simpleui to unfold admin
  • Add more default pages

_EOF_

DeepSeek+Claude join forces to drive the upgrade of the DjangoStarter 3.1 framework using AI.

本文作者:
程序设计实验室
版权声明:
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

相关文章

讨论

共 0 条

良言一句三冬暖,恶语伤人六月寒。

加载评论中…

DeepSeek+Claude join forces to drive the upgrade of the DjangoStarter 3.1 framework using AI. · StarBlog