Сохранение формы Django

#python #django #django-models #django-forms #django-views

#python #django #django-модели #django-формы #django-представления

Вопрос:

Я хотел бы поделиться с вами своим кодом, чтобы найти решение. У меня есть Django form . Я хотел бы сохранить данные, только если нет другого объекта с такими же данными. Другими словами, объекты должны быть уникальными.

Если объект не существует, я сохраняю его, иначе я отображаю форму с сообщением об ошибке «Объект уже существует с этими функциями».

Это моя модель:

 def guide_path(instance, filename):
    # file will be uploaded to MEDIA_ROOT/guides/<guide_id>
    new_filename = f'guides/{instance.site.id}'
    if instance.profile_type:
        new_filename  = f'_{instance.profile_type}'
    if instance.profile_level:
        new_filename  = f'_{instance.profile_level}'
    if instance.language:
        new_filename  = f'_{instance.language}'
    name, ext = os.path.splitext(filename)
    if ext:
        new_filename  = ext

    return new_filename


class UserGuide(models.Model):
    """ A class for storing user guides depending on profiles """
    objects = models.Manager()

    site = models.ForeignKey(WebApplication, on_delete=models.PROTECT, related_name='guides',
                             verbose_name=_('application'))
    file = models.FileField(verbose_name='file', upload_to=guide_path)
    profile_type = models.CharField(verbose_name=_('profile type'), choices=UserProfile.USER_TYPES, max_length=2,
                                    null=True, blank=True)
    profile_level = models.CharField(verbose_name=_('profile level'), choices=UserProfile.USER_ROLES, max_length=2,
                                     null=True, blank=True)
    language = models.CharField(verbose_name=_('language'), choices=settings.LANGUAGES, max_length=2, default='en')

    class Meta:
        verbose_name = _('user guide')
        verbose_name_plural = _('user guides')
        unique_together = ('site', 'profile_type', 'profile_level', 'language')
  

Это моя форма:

 class UserGuideForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    class Meta:
        model = UserGuide
        fields = ['site', 'file', 'profile_type', 'profile_level', 'language']
        widgets = {
            'file': CustomFileInput(attrs={'class': 'clearablefileinput'}),
        }
  

И это мое мнение:

 class UserGuideUpdateView(UpdateView):
    """ Display a form to create a userguide

        **Context**

        ``subtitle``
            Title of the page

        **Template:**

        :template:`app/generic_form.html`
    """
    model = UserGuide
    form_class = UserGuideForm
    success_url = reverse_lazy('userguide-list')
    template_name = 'app/form_userguide.html'
    permission_required = 'app.change_userguide'

    def get_object(self, queryset=None):
        pk = self.kwargs.get('pk')
        return get_object_or_404(UserGuide, pk=pk)

    def get_title(self):
        return _('Edit user guide: ')

    def get_context_data(self, **kwargs):
        context = super(UserGuideUpdateView, self).get_context_data(**kwargs)
        context.update({
            'subtitle': self.get_title(),
        })
        return context

    def form_valid(self, form):
        site = form.cleaned_data['site']
        file = form.cleaned_data['file']
        profile_type = form.cleaned_data['profile_type']
        profile_level = form.cleaned_data['profile_level']
        language = form.cleaned_data['language']

        userguide = UserGuide.objects.filter(site=site.id, profile_type=profile_type, profile_level=profile_level, language=language)
        if userguide.exists():
            messages.error(self.request, _('A user guide for that profile and language already exists'))
            HttpResponseRedirect(self.template_name)
        else:
            pass
        return super().form_valid(form)
  

Как я могу добавить условие, если мой объект уже существует, не сохранять форму и возвращать форму с сообщением об ошибке?

Спасибо

Комментарии:

1. Форма уже сделает это, потому что вы определили unique_together в модели. Нет необходимости в каком-либо коде form_valid .

2. Я определил unique_together , но я могу сохранить объект без ошибок, даже если существует другой объект с теми же данными

3. @DanielRoseman Если поля есть NULL , я могу сохранить x раз один и тот же объект. unique_together работает, если поля не NULL

4. Кроме того, не устанавливайте null=True значение a CharField , это плохая практика (она допускает два «пустых» типа: пустую строку и null). Но поскольку language и site не может быть нулевым, как вы могли бы сохранить с нулевыми полями в первую очередь?

5. @dirkgroten Вы правы, profile_level и profile_type они равны нулю. site и language не являются нулевыми. Однако я могу сохранить свою форму с полями, заполненными следующим образом. Проблема, похоже, связана с profile полями. Как пустое и пустое поле, unique_together не работает нормально. Может быть, мне нужно удалить unique_together и установить проверку на мой взгляд?