I am new to Django and I am trying to learn by practicing with some project but I am stuck with this problem, I want to return the information of the History model to the authenticated user according to its id_user. The problem appears when the user gives the submit of the form.
The message that he gives me is this:
NOT NULL constraint failed: history.user_id
models.py
from django.db import models
from django.contrib.auth.models import User
class History(models.Model):
DAY35 = '35 days'
DAY45 = '45 days'
HISTORY_DAYS = (
(DAY35, '35 days'),
(DAY45, '45 days'),
)
user = models.ForeignKey(User, on_delete=models.CASCADE)
amount = models.FloatField(default=10)
days = models.CharField(
max_length=7,
choices=HISTORY_DAYS,
default=DAY35,
)
def is_upperclass(self):
return self.days in (self.DAY35, self.DAY45)
views.py
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
from django.views.generic.edit import CreateView
from .forms import HistoryForm
from .models import History
#method_decorator(login_required, name='dispatch')
class HistoryCreate(CreateView):
model = History
fields = ['amount', 'days']
success_url = reverse_lazy('history')
form_class = HistoryForm
forms.py
from django import forms
from .models import MiningHistory
class HistoryForm(forms.ModelForm):
class Meta:
model = History
fields = ['amount', 'days']
widgets = {
'amount': forms.NumberInput(attrs={'class':'x', 'placeholder':'0.00'}),
'days': forms.Select(attrs={'class':'x'}),
}
A History instance must have a non null user field. However you are not specifying the user related the History object you're creating.
In case you dont want to add the user, update you're model's user field :
user = models.ForeignKey(User, on_delete=models.CASCADE,blank=True,null=True)
If you want to associate the user field with the logged in user, update your views :
#method_decorator(login_required, name='dispatch')
class HistoryCreate(CreateView):
model = History
fields = ['amount', 'days']
success_url = reverse_lazy('history')
form_class = HistoryForm
def form_valid(self, form_class ):
form_class.instance.user= self.request.user
return super().form_valid(form)
Don't forget to add user to your form fields.
PS : Don't add user to your views modifiable fields. Check this for more details.
Related
models.py
from django.db import models
from accounts.models import User
# Create your models here.
class Customer(models.Model):
user_customer = models.OneToOneField(User)
customer_name = models.CharField(max_length=100,blank=True)
phone_no = models.CharField(max_length=100,blank=True)
inserted = models.DateTimeField(auto_now_add=True,null=True,blank=True)
created = models.DateTimeField(auto_now=True,)
views.py
from django.shortcuts import render,redirect
from django.views.generic.edit import CreateView
from accounts.models import User
from accounts.forms import RegisterForm
from .forms import CustomerRegistration
from .models import Customer
def CustomerSignupView(request):
r_form = RegisterForm(request.POST or None)
c_form = CustomerRegistration(request.POST or None)
context = {
"r_form":r_form ,
"c_form":c_form ,
}
if r_form.is_valid() and c_form.is_valid():
instance = r_form.save(commit=False)
instance.is_customer = True
instance.save()
c_form.save()
return redirect("/")
return render(request,"customerregister.html",context)
forms.py
from django import forms
from .models import Customer
class CustomerRegistration(forms.ModelForm):
class Meta:
model = Customer
fields = ('customer_name','phone_no',)
I have two separate forms - RegisterationForm(RF) and CustomerRegistrationForm(CRF).
CRF inherits RF, I want to save two forms in single view i.e.CustomerSignupView.
While submitting the forms Intergrity error pops up, and the data saved is only from RegistrationForm.
How do I save both forms in thier respective table with integrity maintained.
Thanks.
You haven't shown your forms, but it looks as if you have to set the user before you save the customer to the database:
if r_form.is_valid() and c_form.is_valid():
instance = r_form.save(commit=False)
instance.is_customer = True
instance.save()
customer = c_form.save(commit=False)
customer.user_customer = instance
customer.save()
return redirect("/")
You have to create a User from accounts.models before creating you Customer, if your r_form is a instance of User your c_form will fail because user is required to c_form be valid
if r_form.is_valid():
instance = r_form.save(commit=False)
instance.is_customer = True
instance.save()
if c_form.is_valid():
customer = c_form.save(commit=False)
customer.user_customer = instance
customer.save()
return redirect("/")
Suggestion: why you not Inherite User to your Customer since your Customer is once User
from accounts.models import User
class Costumer(User):
...
This way you can setup the Costumer and User in just one form, is easy to acess the data from Costumer.
All other data is saved ideally but as shown below, the user id part shows as a pull down bar and a null value which should be a signed-in username.
What's wrong with my code?
The database page
Here's my code.
views.py
from .models import Markers
from .forms import AddMarkersInfo
from django.http import HttpResponse
def addinfo(request):
if request.method == 'POST':
mks = AddMarkersInfo(request.POST)
if mks.is_valid():
submit = mks.save(commit=False)
submit.user = request.user
submit.save()
name = mks.cleaned_data['name']
address = mks.cleaned_data['address']
description = mks.cleaned_data['description']
type = mks.cleaned_data['type']
lat = mks.cleaned_data['lat']
lng = mks.cleaned_data['lng']
Markers.objects.get_or_create(name=name, address=address, description=description, type=type, lat=lat, lng=lng)
return render(request, 'home.html', {'mks': mks })
else:
mks = AddMarkersInfo()
return render(request, 'home.html', {'mks': mks})
models.py
from django.db import models
from django.contrib.auth.models import User
from django.conf import settings
from django.contrib.auth import get_user_model
def get_sentinel_user():
return get_user_model().objects.get_or_create(username='deleted')[0]
class Markers(models.Model):
User = settings.AUTH_USER_MODEL
use_id= models.ForeignKey(User, null=True, on_delete=models.SET(get_sentinel_user),)
name = models.CharField(max_length=60,default = 'name')
address = models.CharField(max_length=100,default = 'address')
description = models.CharField(max_length=150, default='description')
types = (
('m', 'museum'),
('s', 'school'),
('r', 'restaurant'),
('o', 'other'),
)
type = models.CharField(max_length=60, choices=types, default='museum')
lat = models.IntegerField()
lng = models.IntegerField()
forms.py
from django import forms
from maps.models import Markers
class AddMarkersInfo(forms.ModelForm):
class Meta:
model = Markers
fields = ['name','address','description', 'type','lat','lng',]
Well, first of all, you should remove the lines from django.contrib.auth.models import User and User = settings.AUTH_USER_MODEL in models.py if you are going to use settings.AUTH_USER_MODEL. You should use only one of the two.
And you can change your field to:
use_id= models.ForeignKey(settings.AUTH_USER_MODEL, ...
Secondly, it seems like you are duplicating the creation. The lines
submit = mks.save(commit=False)
submit.user = request.user
submit.save()
already create an Markers instance, so there is no need to call Markers.objects.get_or_create(... after that.
And, according to you models, the field should be submit.use_id instead of submit.user.
Now, if I understand your question correctly you want to make the use_id field read-only in your form/template.
I don't know why that field is even showing up in your form, since it is not listed in your forms Meta.fields.
You could try something like setting the widget attribute readonly:
class AddMarkersInfo(forms.ModelForm):
class Meta:
model = Markers
fields = ['use_id', 'name', 'address', 'description', 'type', 'lat', 'lng']
widgets = {
'use_id': forms.Textarea(attrs={'readonly': 'readonly'}),
}
I am a Django newbie working with Django CBVs and having difficulty setting initial values for my ModelForm. To give an overview, I am trying to learn by creating a simple messaging app.
Here is my code:
models.py
import datetime
from django.contrib.auth.models import User
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
class Message(models.Model):
subject = models.CharField(_("Subject"), max_length=100)
body = models.TextField(_("Body"))
sender = models.ForeignKey(User, db_index=True, related_name='sent_messages')
recipient = models.ForeignKey(User, db_index=True, related_name='received_messages')
parent_msg = models.ForeignKey('self', related_name='next_messages', null=True, blank=True)
forms.py
from django.forms import ModelForm
from .models import Message
class MessageForm(ModelForm):
class Meta:
model = Message
exclude = ('sender', 'recipient', 'parent_msg',)
views.py
class MessageCreateView(CreateView):
form_class = MessageForm
model = Message
template_name = 'messages/compose.html'
def form_valid(self, form):
form.instance.sender = self.request.user
return super(MessageCreateView, self).form_valid(form)
urls.py
...
url(r'^compose/(?P<recipient>[\w.#+-]+)/$', MessageCreateView.as_view(), name='messages_compose_to'),
...
As you can see from the urls.py file, I am using the 'recipient' parameter as such: http://localhost:8000/members/compose/someusername
Now my problem is that I wish to open the compose message view, and initialize the recipient field by getting the username from the URL, then using the username from the url to get User with that particular username, and instantiate the form with it.
Where do I do this, in the view itself or in the form? Unless their is a better way of how to handle this.
You can add get_initial() method to return appropriate dict, something as below.
class MessageCreateView(CreateView):
...
def get_initial(self):
data = { 'recipient':
User.objects.get(username=self.kwargs.get('recipient'))
}
return data
Handle error appropriately.
I'm trying to create an object in Django using the standard class based views and form libraries. Three fields in my form are dependent upon a domain variable captured from the URL pattern. My questions are:
How do I access domain within CreateSubscription so that I can set Subscription.site to Site.objects.filter(domain=domain)[0]?
How do I limit the dropdown fields rendered from CreateSubscriptionForm so that plan displays only SubscriptionPlan.objects.filter(site=Site.objects.filter(domain=domain)[0]) and payment_profile is limited to PaymentProfile.objects.filter(user=request.user)?
For clarity's sake, the domain in r'^subscribe/(?P<domain>\w+\.\w+)/$' is unrelated to my own site's domain. The django.contrib.sites framework won't help me here.
Thanks in advance for helping me untangle all of these CBV methods. :)
The URL pattern is:
from django.conf.urls import patterns, url
from accounts.views import *
url(r'^subscribe/(?P<domain>\w+\.\w+)/$',
CreateSubscription.as_view(), name='subscribe_to_site'),
)
The view in question is:
from accounts.forms import *
from accounts.models import *
class CreateSubscription(CreateView):
model = Subscription
form_class = CreateSubscriptionForm
def form_valid(self, form):
form.instance.user = self.request.user
return super(CreateSubscription, self).form_valid(form)
The relevant models are:
from django.conf import settings
from django.contrib.sites.models import Site
from django.db import models
class PaymentProfile(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
class SubscriptionPlan(models.Model):
site = models.ForeignKey(Site)
name = models.CharField(max_length=40)
class Subscription(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
site = models.ForeignKey(Site)
plan = models.ForeignKey(SubscriptionPlan)
payment_profile = models.ForeignKey(PaymentProfile)
And, finally, my form is:
from accounts.models import *
class CreateSubscriptionForm(forms.ModelForm):
class Meta:
model = Subscription
exclude = ('user', 'site', )
To access the data passed to the view, use self.args and self.kwargs
from accounts.forms import *
from accounts.models import *
class CreateSubscription(CreateView):
model = Subscription
form_class = CreateSubscriptionForm
def form_valid(self, form):
form.instance.user = self.request.user
form.instance.site = Site.objects.get(domain=self.kwargs['domain'])
return super(CreateSubscription, self).form_valid(form)
To restrict the dropdown content, you need to set the queryset for those fields. Very basically, something along these lines:
class CreateSubscriptionForm(forms.ModelForm):
plan = forms.ModelChoiceField(
queryset=SubscriptionPlan.objects.filter(xxx)
)
...
class Meta:
model = Subscription
exclude = ('user', 'site', )
This can also be done inside the view so that you have access to the domain.
class CreateSubscription(CreateView):
model = Subscription
form_class = CreateSubscriptionForm
def get_form(self, form_class):
"""
Returns an instance of the form to be used in this view.
"""
form = super(CreateSubscription, self).get_form(form_class)
form.fields['plan'].queryset = SubscriptionPlan.objects.filter(site__domain=self.kwargs['domain'])
return form
...
def form_valid(self, form):
form.instance.user = self.request.user
form.instance.site = Site.objects.get(domain=self.kwargs['domain'])
return super(CreateSubscription, self).form_valid(form)
I am working on form models and get this error:
global name 'AdForm' is not defined
In my view I have:
from django.template import RequestContext, loader
from django.http import HttpResponse
from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required
from django import forms
#login_required
def create(request):
if request.POST:
ad = AdForm(request.POST)
if ad.is_valid():
test = 'valid'
else:
test = 'invalid'
else:
test = 'none'
template = loader.get_template('ads/create.html')
context = RequestContext(request, {
'test': test
})
return HttpResponse(template.render(context))
However it is not picking up my model. My model in my view is:
from django.db import models
from django.forms import ModelForm
TYPE_CHOICES = (
'Image',
'Code',
)
SIZE_CHOICES = (
'Leaderboard',
'Banner',
'Skyscraper',
'Square',
)
class Ad(models.Model):
title = models.CharField(max_length=40)
type = models.CharField(max_length=7)
size = models.CharField(max_length=16)
clicks = models.IntegerField()
media = models.ImageField(upload_to='ads')
link = models.URLField(null=True)
created = models.DateTimeField(auto_now_add=True)
expires = models.DateTimeField(null=True)
def __unicode__(self):
return self.name
class AdForm(ModelForm):
class Meta:
model = Ad
Does anyone know why it is not picking up the form model?
Thanks from a noob.
At the top of your view, you need:
from .models import AdForm
Also, forms usually go in forms.py, not with the models.