'NoneType' object has no attribute 'user' - django

I'm trying to take input of a domain name (domainNm) and an email address at a domain (emailVerified) and submit them via modelform based off a table [Tld] .
It appears, it is failing to save() the foreign key (from the currently authenticated user)
domain.FKtoClient = user_info
What am I doing wrong here?
forms.py
class SubmitDomain(ModelForm):
domainNm = forms.CharField(initial=u'', label='Enter your domain')
emailVerified = forms.EmailField(label='Email at Domain')
class Meta:
model = Tld #Create form based off Model for Tld
fields = ['domainNm','emailVerified']
def save(self, request=None):
instance = self.cleaned_data
#domain = instance["domainNm"])
domains = Tld.objects.filter(domainNm=instance["domainNm"])
if len(domains) == 0:
domain = Tld()
else:
domain = domains[0]
user_info = request.user
unique_id = int(uuid.uuid4())
domain.generated_hash = str(unique_id)
domain.entered_email = instance["emailVerified"]
domain.domainNm = instance["domainNm"]
domain.FKtoClient = user_info
domain.save()
Thanks!

def save(self, request=None):
You assign a default value of None to request in the definition of save, so what happens when the caller of save doesn't pass an instantiated request?
user_info = request.user #request is None here
That will throw the error you see. To mitigate, add a simple if request is not None or similar statement.
EDIT
After seeing your views.py, you are passing request.POST to SubmitDomain's __init__ magic method, which you have not defined. The way you have your modelform defined above, you would have to pass the request to save(), not __init__(), i.e.
form.save(request)

Related

Django rest framework - Serializer always returns empty object ({})

I am creating first rest api in django using django rest framework
I am unable to get object in json format. Serializer always returns empty object {}
models.py
class Shop(models.Model):
shop_id = models.PositiveIntegerField(unique=True)
name = models.CharField(max_length=1000)
address = models.CharField(max_length=4000)
serializers.py
class ShopSerializer(serializers.ModelSerializer):
class Meta:
model = Shop
fields = '__all__'
views.py
#api_view(['GET'])
def auth(request):
username = request.data['username']
password = request.data['password']
statusCode = status.HTTP_200_OK
try:
user = authenticate(username=username, password=password)
if user:
if user.is_active:
context_data = request.data
shop = model_to_dict(Shop.objects.get(retailer_id = username))
shop_serializer = ShopSerializer(data=shop)
if shop:
try:
if shop_serializer.is_valid():
print('is valid')
print(shop_serializer.data)
context_data = shop_serializer.data
else:
print('is invalid')
print(shop_serializer.errors)
except Exception as e:
print(e)
else:
print('false')
else:
pass
else:
context_data = {
"Error": {
"status": 401,
"message": "Invalid credentials",
}
}
statusCode = status.HTTP_401_UNAUTHORIZED
except Exception as e:
pass
return Response(context_data, status=statusCode)
When i try to print print(shop_data) it always returns empty object
Any help, why object is empty rather than returning Shop object in json format?
Edited:
I have updated the code with below suggestions mentioned. But now, when shop_serializer.is_valid() is executed i get below error
{'shop_id': [ErrorDetail(string='shop with this shop shop_id already exists.', code='unique')]}
With the error it seems it is trying to update the record but it should only get the record and serialize it into json.
You're using a standard Serializer class in this code fragment:
class ShopSerializer(serializers.Serializer):
class Meta:
model = Shop
fields = '__all__'
This class won't read the contend of the Meta subclass and won't populate itself with fields matching the model class. You probably meant to use ModelSerializer instead.
If you really want to use the Serializer class here, you need to populate it with correct fields on your own.
.data - Only available after calling is_valid(), Try to check if serializer is valid than take it's data

func form.is_valid() return all time False

I have a form that takes "username" from the User model and my own "email" field. I want to change this data for the User model. At first glance everything seems to work fine, the name changes and the mail is the same. But if I only change the mail and I don't touch the username, I get an error: "A user with this name already exists.
file views.py:
form=UserUpdateForm(request.POST)
if form.is_valid():
user=User.objects.get(username=self.request.user)
user.username=form.cleaned_data.get('username')
user.email=form.cleaned_data.get('email')
user.save()
file forms.py:
class UserUpdateForm(forms.ModelForm):
email = forms.EmailField(required=False)
def __init__(self, *args, **kwargs):
super(UserUpdateForm, self).__init__(*args, **kwargs)
if 'label_suffix' not in kwargs:
kwargs['label_suffix'] = '*'
self.fields['username'].widget = forms.TextInput(attrs={'class':'input-text'})
self.fields['email'].widget = forms.EmailInput(attrs={'class':'input-text'})
class Meta:
model = User
fields = ("username","email",)
def clean_email(self):
cleaned_data = super(UserUpdateForm,self).clean()
email=cleaned_data.get('email')
return email
From the doc,
A subclass of ModelForm can accept an existing model instance as the keyword argument instance; if this is supplied, save() will update that instance. If it’s not supplied, save() will create a new instance of the specified model
If you are updating the data, you have to pass the instance to the form as,
# on updationg
form = UserUpdateForm(data= request.POST, instance=your_mode_instance)
Since you are not passing the instance for the second time, Django thinks that the operation is a row insert instead of row update

App works with ModelChoiceField but does not work with ModelMultipleChoiceField

I am trying to retrieve user input data in a django page. But I am unable to choose to multichoice field. I have tried multiple alternatives to no relief.
self.fields['site'].queryset=forms.ModelMultipleChoiceField(queryset=sites.objects.all())
self.fields['site'] = forms.ModelChoiceField(queryset=sites.objects.filter(project_id=project_id))
self.fields['site'].queryset = forms.MultipleChoiceField(widget=forms.SelectMultiple, choices=[(p.id, str(p)) for p in sites.objects.filter(project_id=project_id)])
forms.py
class SearchForm(forms.Form):
class Meta:
model= images
fields=['site']
def __init__(self,*args,**kwargs):
project_id = kwargs.pop("project_id") # client is the parameter passed from views.py
super(SearchForm, self).__init__(*args,**kwargs)
self.fields['site'] = forms.ModelChoiceField(queryset=sites.objects.filter(project_id=project_id))
views.py
def site_list(request, project_id):
form = SearchForm(project_id=project_id)
site_list = sites.objects.filter(project__pk=project_id).annotate(num_images=Count('images'))
template = loader.get_template('uvdata/sites.html')
if request.method == "POST":
image_list=[]
form=SearchForm(request.POST,project_id=project_id)
#form=SearchForm(request.POST)
#site_name=request.POST.get('site')
if form.is_valid():
site_name=form.cleaned_data.get('site')
print(site_name)
I expect to get a multiselect field but I end up getting this error:
Exception Value:
'site'
Exception Location: /home/clyde/Downloads/new/automatic_annotator_tool/django_app/search/forms.py in init, line 18
(line 18:self.fields['site'].queryset = forms.MultipleChoiceField(widget=forms.SelectMultiple, choices=[(p.id, str(p)) for p in sites.objects.filter(project_id=project_id)]))
You are not defining your form correctly. The documentation shows you how to do this.
In your case it would be something like this:
class SearchForm(forms.Form):
site = forms.ModelMultipleChoiceField(queryset=Sites.object.none())
def __init__(self,*args,**kwargs):
project_id = kwargs.pop("project_id")
super(SearchForm, self).__init__(*args,**kwargs)
self.fields['site'].queryset = Sites.objects.filter(project_id=project_id))
You also appear to be confusing regular Form and ModelForm, as Meta.model is only used in ModelForm whereas you are using a regular Form. I suggest you read up on the difference in the documentation before you proceed.

django form use excluded field

with django 1.5.1 I try to use the django form for one of my models.
I dont want to add the "user" field (Foreignkey) somewhere in the code instead of letting the user deceide whoes new character it is.
My Code:
Model:
class Character(models.Model):
user = models.ForeignKey(User)
creation = models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')
name = models.CharField(max_length=32)
portrait = models.ForeignKey(Portrait)
faction = models.ForeignKey(Faction)
origin = models.ForeignKey(Origin)
The form:
class CreateCharacterForm(forms.ModelForm):
class Meta:
model = Character
fields = ['name', 'portrait', 'faction', 'origin']
The view:
def create_character(request, user_id):
user = User.objects.get(id=user_id)
if request.POST:
new_char_form = CreateCharacterForm(request.POST)
if new_char_form.is_valid():
new_char_form.save()
return HttpResponseRedirect('%s/characters/' % user_id)
else:
return render_to_response('create.html',
{'user': user, 'create_char':new_char_form},
context_instance=RequestContext(request))
else:
create_char = CreateCharacterForm
return render_to_response('create.html',
{'user': user, 'create_char': create_char},
context_instance=RequestContext(request))
I have tried to use a instance to incluse the userid already. i've tried to save the userid to the form before saving it, or changing the save() from my form.
I keep getting the error that character.user cant be null
I have to tell that im pretty new to django and im sure one way or another it should be possible
Can someone please help me out?
Its explained well in document model form selecting fields to use
You have to do something like this in your view
...
if request.POST:
new_char_form = CreateCharacterForm(request.POST)
if new_char_form.is_valid():
#save form with commit=False
new_char_obj = new_char_form.save(commit=False)
#set user and save
new_char_obj.user = user
new_char_obj.save()
return HttpResponseRedirect('%s/characters/' % user_id)
else:
...

query in django model

I am using django and as I am pretty new I have some questions.
I have one model called Signatures and a ModelForm called SignatureForm in my models.py file:
class Signature(models.Model):
sig = models.ForeignKey(Device)
STATE = models.CharField(max_length=3, choices=STATE_CHOICES)
interval = models.DecimalField(max_digits=3, decimal_places=2)
verticies = models.CharField(max_length=150)
class SignatureForm(ModelForm):
class Meta:
model = Signature
widgets = {
'verticies': HiddenInput,
}
To use it, I wrote the following function in views.py:
def SigEditor(request):
# If the form has been sent:
if request.method == 'POST':
form = SignatureForm(request.POST)
# If it is valid
if form.is_valid():
# Create a new Signature object.
form.save()
return render_to_response('eQL/sig/form_sent.html')
else:
return render_to_response('eQL/sig/try_again.html')
else:
form = SignatureForm()
return render_to_response('eQL/sig/showImage.html', {'form' : form})
However, I don't want to save all the new signatures. I mean, if the user introduces a new signature of the device A and state B, I would like to check if I have some signature like that in my database, delete it and then save the new one so that I have only one signature saved for each device and state.
I have tried something like this before saving it but of course is not working:
q = Signature.objects.filter(sig = s, STATE = st)
if q.count != 0:
q.delete()
form.save()
can anyone help?? thanks!!
If you really do want to delete, why not?
Signature.objects.filter(sig=s, STATE=st).delete()
If you only ever want one combination of those items, you could use get_or_create, and pass in the instance to your ModelForm.
instance, created = Signature.objects.get_or_create(sig=s, STATE=st)
form = SignatureForm(request.POST, instance=signature)
# edit instance.
Or put it in your form save logic:
class SignatureForm(ModelForm):
def save(self, *args, **kwargs):
data = self.cleaned_data
instance, created = Signature.objects.get_or_create(sig=data['sig'], STATE=data['state'])
self.instance = instance
super(SignatureForm, self).save(*args, **kwargs)