Django - How to fix unique constraint fields - python

I'm making a hobby project and I've got the following model:
from django.contrib.auth.models import User
from django.db import models
class Group(models.Model):
name = models.CharField(blank=False, max_length=25)
description = models.CharField(max_length=50, blank=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=False)
def __str__(self):
return self.name
class Meta:
ordering = ('name', )
# my intention is that one user cannot have more than one group with the same name
unique_together = ('name', 'user')
I would like to make it possible for the user to create new groups by using this generic class based view.
from django.urls import reverse_lazy
from django.views import generic
from groups.models import Group
class GroupCreate(generic.CreateView):
model = Group
fields = [
'name',
'description'
]
success_url = reverse_lazy('ideas:list')
template_name = 'groups/group_create.html'
def form_valid(self, form):
form.instance.user = self.request.user
return super(GroupCreate, self).form_valid(form)
As long as I don't try to make an error by sending an existing group's name, everything works fine. But if I send an existing group's name (same user!), I get the following error:
IntegrityError at /groups/create
UNIQUE constraint failed: groups_group.name, groups_group.user_id
Why does it occur? How could I fix it or catch the error?
I'm using Django 2.0.2

You can check at the time of creating the group.
from django.contrib import messages
def form_valid(self, form):
form.instance.user = self.request.user
name = form.cleaned_data['name']
if Group.objects.filter(name=name, user=self.request.user).exists():
messages.error(self.request, 'An Group with this name already exists.')
return self.render_to_response(self.get_context_data(form=form))
else:
form.instance.name= name
messages.success(self.request, 'Congratulations!! Your Group is created successfully.')
return super(GroupCreate, self).form_valid(form)

This occurs because you declared a constraint:
unique_together = ('name', 'user')
Just remove this constraint.

Related

How to link login user to post that he created?

I'm learning django and I made the tutorial on django site. I thought that I could link user to poll that he created but I'm struggling with it. When I'm logged in and creating a poll I can't see user name. In database column author_id has value null. I would appreciate every help.
Here is my code
from django.db import models
from django.utils import timezone
import datetime
from django.contrib import auth
# Create your models here.
User = auth.get_user_model()
class Question(models.Model):
question_text = models.CharField(max_length=200)
author = models.ForeignKey(User, on_delete=models.CASCADE, null=False)
def __str__(self):
return self.question_text
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
class User(auth.models.User, auth.models.PermissionsMixin):
def __str__(self):
return "#{}".format(self.username)
forms.py:
class UserCreateForm(UserCreationForm):
class Meta:
fields = ('username', 'email', 'password1', 'password2')
model = get_user_model()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['username'].label = 'Display Name'
self.fields['email'].label = 'Email Address'
class CreatePollForm(forms.ModelForm):
class Meta:
model = Question
fields = ('question_text',)
and views.py
class CreatePoll(LoginRequiredMixin, generic.CreateView):
form_class = forms.CreatePollForm
success_url = reverse_lazy('pollapp:index')
template_name = 'polls/createPoll.html'
Since your CreatePollForm only assigns the question_text field, you need to assign the author in code. A CreateView is a FormView which does the saving of the form in its form_valid() method. So in your CreateView, you want to override that method:
# in class CreatePoll
def form_valid(self, form):
question = form.save(commit=False) # fetch the new question, don't save
question.author = self.request.user # assign the user
question.save() # now save
return super().form_valid(form)
It isn't clear how you could end up with a null value for the author_id, that should have raised an IntegrityError. Are you sure you ran makemigrations and migrate in the current state?

How to save current CustomUser as person field in my Melk model? There is OneToMany relation

I am curious to solve this problem.
I use CustomUser
I have 2 models CustomUser and Melk
In my forms.py, when i use 'person' as field, it means user can see all the users but I want current user fill the form and based on onetomany relation, person field fills by id of current user.
I deleted 'person' field in forms and tried to use of
form.users_melk.person_id = request.user or
Melk.objects.create(person_id = user_id)
but it does not solved.
models.py
class CustomUser(AbstractUser):
def __str__(self):
return self.email
class Melk(models.Model):
category = models.CharField(max_length=50)
type_deal= models.CharField(max_length=50)
person = models.ForeignKey('CustomUser', on_delete=models.DO_NOTHING)
def __str__(self):
return self.category
forms.py
class MelkForm(forms.ModelForm):
class Meta:
model = Melk
fields = ('category', 'type_deal', 'person')
views.py
#login_required(login_url="home")
def melk_new(request):
f = MelkForm(request.POST)
if f.is_valid():
f.save()
return render(request,'melk_new.html', { 'form': f})
When i delete 'person' field in forms.py this error appears:
IntegrityError at /users/melk_new/ NOT NULL constraint failed:
users_melk.person_id Request Method: POST Request
URL: http://127.0.0.1:8000/users/melk_new/ Django Version: 2.1.7
I solved the problem f.person= request.user.id

(Django) Model of particular person with this User already exists

Dear StackOverFlow community,
Basing on a built-in user User model I've created my own model class called "ModelOfParticularPerson". The structure of it looks like this:
class ModelOfParticularPerson(models.Model):
user = models.OneToOneField(User)
nickname = models.CharField(max_length=100, null=True, unique=False)
uploaded_at = models.DateTimeField(auto_now_add=True, null=True)
email_address = models.EmailField(max_length=200, blank=False, null=False, help_text='Required')
description = models.CharField(max_length=4000, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True, blank=True)
Unfortunately, after loggin in with the usage of particular account, whenever I am trying to reedit the profile, I do get following error:
"Model of particular person with this User already exists."
Any advice is priceless.
Thanks.
ps.
views.py:
[..]
#method_decorator(login_required, name='dispatch')
class ProfileUpdateView(LoginRequiredMixin, UpdateView):
model = ModelOfParticularPerson
form_class = ModelOfParticularPersonForm
success_url = "/accounts/profile/" # You should be using reverse here
def get_object(self):
# get_object_or_404
return ModelOfParticularPerson.objects.get(user=self.request.user)
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
def post(self, request):
form = ModelOfParticularPersonForm(self.request.POST, self.request.FILES)
if form.is_valid():
print("FORM NOT VALID!")
profile = form.save(commit=False)
profile.user = self.request.user
profile.save()
return JsonResponse(profile)
else:
return render_to_response('my_account.html', {'form': form})
urls.py:
urlpatterns = [
[..]
url(r'^login/$', auth_views.LoginView.as_view(template_name='login.html'), name='login'),
url(r'^accounts/profile/$', ProfileUpdateView.as_view(template_name='my_account.html'), name='my_account'),
]
forms.py
class ModelOfParticularPersonForm(ModelForm):
class Meta:
model = ModelOfParticularPerson
fields = '__all__'
widgets = {
'user':forms.HiddenInput(),
'uploaded_at':forms.HiddenInput(),
'created':forms.HiddenInput(),
}
You need to pass the instance to the form, otherwise Django will try to create a new object when you save it.
def post(self, request):
form = ModelOfParticularPersonForm(instance=self.get_object(), self.request.POST, self.request.FILES)
...
You should try to avoid overriding get or post when you're using generic class based views. You can end up losing functionality or having to duplicate code. In this case, it looks like you can remove your post method. In the form_valid method you can return a JsonResponse. You shouldn't have to set form.instance.user if you are updating an existing object.
def form_valid(self, form):
profile = form.save()
return JsonResponse(profile)
Finally, you should leave fields like user and uploaded_at out of the model form instead of making them hidden fields.
You're creating new forum in your post method of view, but you're not passing existing model object to it. That leads to creation of new model, which fails, because object already exists.
Instead of overwritting post method, put saving of object inside is_valid method and use already provided form object (passed to you by method parameter).

How to set dynamic initial values to django modelform field

I'm kinda new to django, I need to set a dynamic initial value to my modelform field. I have a database field in my model name 'author' it has a foreignkey that connects it to the django user model. I need to automatically set this to the current user anytime a user fills in information into the form.
from what I gathered about this problem, I'd have to define an __init__ function inside the MyHouseEditForm below, I'm new to django and all the examples I've seen a pretty confusing.
forms.py
from django import forms
from django.contrib.auth.models import User
from .models import Myhouses
class MyHouseEditForm(forms.ModelForm):
class Meta:
model = Myhouses
fields = ('author','name_of_accomodation', 'type_of_room', 'house_rent', 'availability', 'location', 'nearest_institution', 'description', 'image')
i need to set the value of 'author' to the current user anytime a user logs in.
models.py
from django.db import models
from django.contrib.auth.models import User
class Myhouses(models.Model):
author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name='author')
Available = 'A'
Not_Available = 'NA'
Availability = (
(Available, 'Available'),
(Not_Available, 'Not_Available'),
)
name_of_accomodation = models.CharField(max_length=200)
type_of_room = models.CharField(max_length=200)
house_rent = models.IntegerField(null=True)
availability = models.CharField(max_length=2, choices=Availability, default=Available,)
location = models.CharField(max_length=200)
nearest_institution = models.CharField(max_length=200)
description = models.TextField(blank=True)
image = models.ImageField(upload_to='profile_image')
def __str__(self):
return self.name_of_accomodation
views.py
#login_required
def addlisting(request):
if request.method == 'POST':
form = MyHouseEditForm(request.POST, files=request.FILES)
if form.is_valid():
Houses = form.save(commit=False)
Houses.save()
return redirect('addlisting')
else:
form = MyHouseEditForm()
return render(request, 'houses/addlisting.html', {'form':form })
No need to show author field in form. It would automatically populate with logged in user.
request.user gives you logged in user object. So, you may remove 'author' filed from forms field section and do this:
Houses = form.save(commit=False)
Houses.author = request.user
Houses.save()
I did something like this in the serializer.
I defined a custom create method like this:
class MyhousesSerializer(FlexFieldsModelSerializer):
...
def create(self, validated_data):
validated_data['author'] = self.context['request'].user
newhouse = Myhouses.objects.create(**validated_data)
return newhouse
It shouldn't matter if you use a more regular model serializer.

NOT NULL constraint failed: teams_team.user_id

When I submit a new team as a authenticated user, I get this error is showing. I searched a lot of answers but they say do it null=True or default=1 but I don't want to be it null or something I want to be user's id it. Plus I imported and tried settings.AUTH_USER_MODEL and get_user_model
from django.contrib.auth.models import User
#models.py
class Team(models.Model):
creator = models.ForeignKey(User, related_name='teams', on_delete=models.CASCADE)
name = models.CharField(max_length=20, unique=True)
rank = models.IntegerField(default=0)
#views.py
class TeamsCreateView(generic.CreateView):
model = Team
form_class = TeamCreationForm
#forms.py
class TeamCreationForm(forms.ModelForm):
class Meta:
model = Team
fields = ('name',)
Override the form_valid method, and set user on the form's instance before saving it.
from django.contrib.auth.mixins import LoginRequiredMixin
class TeamsCreateView(LoginRequiredMixin, generic.CreateView):
model = Team
form_class = TeamCreationForm
def form_valid(self, form):
form.user = self.request.user
return super(TeamsCreateView, self).form_valid(form)
Use LoginRequiredMixin to make sure that users can only access the view if they are logged in.

Categories

Resources