Как установить значение по умолчанию или добавить внешний ключ в ModelForm? - PullRequest
0 голосов
/ 12 марта 2020

Контекст:

  • с использованием Django 3.0.4.

У меня есть две модели

  • UserProfil произвольная пользовательская модель, автоматически создаваемая путем регистрации
  • UserList более или менее простого списка списков

Каждый зарегистрированный пользователь может создать новую запись UserList в моей модели давая UserList.name в форме. Если я введу UserList.name и UserList.profile в форму, мой шаблон сгенерирует входные данные, и я смогу ввести любое значение. пока это работает.

Но очевидно, что пользователям не следует разрешать выбирать отношение UserList.profile в шаблоне, потому что в этом случае они могут создать новую запись в списке, относящуюся к другим пользователям. поэтому мне нужно установить значение для текущего пользователя.

Мой подход к сохранению этого отношения заключался в том, что вы видите в SingleListForm.save моих форм. К сожалению, ничего не сохраняется при вводе значения для * 1029. * в моем шаблоне ввода. Отображается только my form_invalid сообщение: "Ошибка, что-то пошло не так" .

Кроме того, я также попытался удалить поле profiler из fields: в моем SingleListForm и попытался сохранить. но потом я получаю сообщение

The above exception (NOT NULL constraint failed: profil_userlist.profiler_id) was the direct cause of the following exception:

Вопрос

Как установить по умолчанию или добавить внешний ключ в ModelForm?


models.py


class UserProfil(models.Model):
    # --- head
    id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
    # --- relation   
    user_con = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    # -- link 
    userlink = models.UUIDField(unique=True, default=uuid4, editable=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    # --- body
    userinfo = models.TextField(null=True, blank=True, help_text="about you")

#---receiver:  if new AUTH.user -> UserProfil create UserProfil entry 
@receiver(post_save, sender=settings.AUTH_USER_MODEL, dispatch_uid="new_profil")
def create_new_profil(sender, instance, created, **kwargs):
        if created:
            UserProfil.objects.create(user_con=instance)

class UserList(models.Model):
    # --- head
    id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
    uvlink = models.UUIDField(unique=True, default=uuid4, editable=False)
    created_at = models.DateTimeField(default=now, editable=False)
    updated_at = models.DateTimeField(auto_now=True)
    # --- relation  
    profiler = models.ForeignKey('UserProfil', on_delete=models.CASCADE)
    # -- body
    name = models.CharField(max_length=50, blank=False, unique=True, help_text="List Name")
    listname_slug = models.SlugField(blank=True)

    # -- # Sluggenerator
    def save(self, *args, **kwargs):
        if not self.listname_slug:
            # Newly created object, so set slug
            self.listname_slug = slugify(self.name)

        super(UserList, self).save(*args, **kwargs)
    # -- # END

    # def get_absolute_url(self):
    #     return reverse("store:mylist", kwargs={"listname_slug": self.listname_slug})

    def __str__(self):
        return "{}".format(self.name[:60]) 

views.py


class SingleListCreateView(CreateView):
    template_name ="store/list/single_list_create.html"
    form_class = SingleListForm
    success_url = reverse_lazy('store:single_list_create_confirmed')
    queryset = UserList.objects.all()

    def form_invalid(self, form):
        msg = "Error something went wrong"
        return self.render_to_response(self.get_context_data(form=form, message=msg))

forms.py


class SingleListForm(ModelForm):

    class Meta:
        model = UserList
        fields = [
            'name',
            'profiler',    
        ]

        labels  = {
        'name':'List Name'
        }


    def __init__(self, *args, **kwargs):
        super(SingleListForm, self).__init__(*args, **kwargs)
        self.fields['name'].help_text

    def save(self, commit=True):
        # --- get the form data, before saving all
        formData = super().save(commit)

        # --- get relation of current user
        setUserProfil = self.request.user.userprofil.id

        # alternative
        # setUserProfil = self.request.user.userprofil

        # -- set relation
        formData.profiler_set.add(setUserProfil)

        # alternative
        # formData.profiler.add(setUserProfil)

        return formData

Решение 1

относится к @ Yellowduck спасибо!

forms.py

class SingleListForm(ModelForm):
    class Meta:
        model = UserList
        fields = [
            'name', 
        ]

        labels  = {
        'name':'List Name'
        }

    def __init__(self, *args, **kwargs):
        super(SingleListForm, self).__init__(*args, **kwargs)
        self.fields['name'].help_text

views.py

class SingleListCreateView(CreateView):
    template_name ="store/list/single_list_create.html"
    form_class = SingleListForm
    success_url = reverse_lazy('store:single_list_create_confirmed')



    queryset = UserList.objects.all()

    def form_valid(self, form):
        profiler = self.request.user.userprofil
        form.instance.profiler = profiler
        return super().form_valid(form)

Решение 2

Я также нашел решение, установив ìnitial в форму и hidden_input в шаблоне

forms.py

class SingleListForm(ModelForm):
    class Meta:
        model = UserList
        fields = [
            'name',
            'profiler',    
        ]

        labels  = {
        'name':'List Name'
        }

        widgets = {
            'profiler': forms.HiddenInput()
            }

    def __init__(self, *args, **kwargs):
        super(SingleListForm, self).__init__(*args, **kwargs)
        self.fields['name'].help_text

просмотров .py

class SingleListCreateView(CreateView):
    template_name ="store/list/single_list_create.html"
    form_class = SingleListForm
    success_url = reverse_lazy('store:single_list_create_confirmed')
    queryset = UserList.objects.all()

    def get_initial(self, *args, **kwargs):
        initial = super(SingleListCreateView, self).get_initial(**kwargs)
        initial['profiler'] = self.request.user.userprofil
        initial['name'] = "hello"
        return initial

1 Ответ

1 голос
/ 12 марта 2020

Сначала удалите поле profiler в вашем SingleListForm, так как вы не хотите, чтобы пользователь мог свободно выбирать профиль. Форма будет содержать только одно поле name, которое именно то, что вы хотите, чтобы пользователь заполнил.

В вашем CreateView переопределите form_valid, чтобы добавить нужный Userprofil объект:

def form_valid(self, form):
    profiler = *your_query_to_get_profiler*
    form.instance.profiler = profiler
    return super().form_valid(form)
...