Django - как добавить элементы, специфичные для пользователя?

Добрый день Stackoverflow, пользователь должен иметь возможность добавлять несколько названий вместо того, чтобы всегда перезаписывать одно добавленное название

\\\ views.py

def edit_profile(request):

    try:
        profile = request.user.userprofile
    except UserProfile.DoesNotExist:
        profile = UserProfile(user=request.user)

    if request.method == 'POST':
        form = UserProfileForm(request.POST, instance=profile)
        if form.is_valid():
            form.save()
            return redirect('/test')
    else:
        form = UserProfileForm(instance=profile)

        return render(request, 'forms.html', {'form': form, 'profile': profile})

\\\models.py

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=1024)

    def __str__(self):
        return str(self.title)

\\\forms.py

class UserProfileForm(forms.ModelForm):

    class Meta:
        model = UserProfile
        fields = ('title',)

Тогда у пользователя есть форма на сайте, где он может добавить конкретное название.

До сих пор, однако, каждый раз, когда пользователь заполняет форму заголовка, значение в базе данных перезаписывается. Как и должно быть: Когда новое название добавляется в форму, оно должно просто добавляться в нее.

В конце я должен иметь возможность, с помощью цикла Foor в шаблоне HTML, отобразить все добавленные заголовки соответствующего пользователя.

Вы знаете, как это сделать?

Вы можете создать новую модель и присвоить новую модель полю ForeignKey.

models.py:

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)

    def __str__(self):
        return ', '.join([title for title in self.titles.all()])


class UserTitle(models.Model):
    title = models.CharField(max_length=1024)
    userprofile = models.ForeignKey(UserProfile, on_delete=models.CASCADE, related_name='titles')
        
    def __str__(self):
        return self.title

views.py:

def edit_profile(request):
    ...
    if request.method == 'POST':
        ...
        if form.is_valid():
            form.instance.userprofile = request.user.userprofile
            form.save()
            return redirect('/test')
    ...

В шаблоне, чтобы сделать цикл for, просто используйте:

{% for title in user.userprofile.titles.all %}
    {{ title }}
{% endfor %}

или если вам нужны только заголовки пользователей в одной строке:

{{ user.userprofile }}

Если вы используете реляционную базу данных, эта функциональность не реально поддерживается для одного поля. Хотя, если вы действительно хотите, вы можете использовать поле JSON, чтобы заставить это работать.

Однако, вероятно, лучше использовать отдельную таблицу для заголовков.

Для этого нужно создать новый Title объект типа:
class Title(models.Model):

Затем создайте отношения "многие-к-одному", используя ForeignKey:

class Title(models.Model): 
    text = models.CharField(max_length=1024)
    user_profile = models.ForeignKey(UserProfile, on_delete=models.CASCADE)

Необходимо использовать метод on_delete. Этот метод удалит все титулы, связанные с UserProfile, если UserProfile будет удален.

Теперь, если вы хотите связать объект title с UserProfile, вы сделаете это следующим образом:

profile = UserProfile(user=request.user)
title = Title.objects.create(text='My Very First Title', user_profile=profile)

Для получения дополнительной информации об отношениях "многие-к-одному" в Django: https://docs.djangoproject.com/en/4.0/topics/db/examples/many_to_one/

Вернуться на верх