I have created this application but the problem I face now is one that has kept me up all night. I want users to be able to see and select only their own categories when they want to create a post. This is part of my codes and additional codes would be provided on request
category model
class Category(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1,related_name='categories_created')
name = models.CharField(max_length = 120)
slug = models.SlugField(unique= True)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
post model
class Post(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1,related_name='posts_created') #blank=True, null=True)
title = models.CharField(max_length = 120)
slug = models.SlugField(unique= True)
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='category_created', null= True)
addition codes would be provided immediately on request. Thanks
View.py in post app
def create(request):
if not request.user.is_authenticated():
messages.error(request, "Kindly confirm Your mail")
#or raise Http404
form = PostForm(request.POST or None, request.FILES or None)
user = request.user
categories = Category.objects.filter(category_created__user=user).distinct()
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instance.save()
create_action(request.user, 'Posts', instance)
messages.success(request, "Post created")
return HttpResponseRedirect(instance.get_absolute_url())
context = {
"form": form,
}
template = 'create.html'
return render(request,template,context)
Form
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = [
"title",
"content",
"category",
]
html
{% if form %}
<form method="POST" action="" enctype="multipart/form-data">{% csrf_token %}
{{ form|crispy|safe }}
<input type="submit" name="submit" value="Publish">
</form>
{% endif %}
What you need to do is well-described here. Basically, you are using ModelForm which generates the form from your model. Your model doesn't know anything about filtering by user, so you will need to explicitly add a QuerySet to your form that only shows the desired categories. Change your "categories = ..." line to something like:
form.category.queryset = Category.objects.filter(user=user)
form.fields['category'].queryset = Category.objects.filter(user=user)</strike>
Related
In my django app I have a User model that has a Boolean field of is_manager.
User model in models.py:
class User(AbstractUser):
name = models.CharField(max_length=15, null=True, blank=True)
last_name = models.CharField(max_length=15, null=True, blank=True)
title = models.CharField(max_length=50, null=True, blank=True)
email = models.EmailField(unique=True)
bio = models.TextField(null=True, blank=True)
company = models.ForeignKey(Company, on_delete=models.DO_NOTHING, null=True)
is_manager = models.BooleanField(default=False)
can_assign = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
I've been trying to create an edit page in order for managers and users to be able to change some of their fields.
Regular users should be able to change their bio and title, and the managers can change the can_assign Boolean.
I have a form that deals with the logic of that in forms.py:
class EditUserForm(ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
if self.user.is_manager:
super().__init__(**kwargs)
else:
super().__init__(**kwargs)
del self.fields['can_assign']
class Meta:
model = User
fields = ['title', 'can_assign', 'bio']
views.py:
#login_required
def editUser(request, pk):
user = User.objects.get(id=pk)
if request.user.is_manager or request.user == user:
#POST
if request.method == 'POST':
form = EditUserForm(request.POST, instance=user, user=request.user)
if form.is_valid():
form.save()
redirect('user-page', pk)
else:
print('nope')
#GET
form = EditUserForm(user=request.user, instance=user)
context = {'user': user, 'form': form}
return render(request, 'users/user_edit.html', context)
else:
return HttpResponse('<h1>Access Denied</h1>')
template:
{% extends 'main.html' %}
{% block content %}
<form method="POST" action="">
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="Submit">
</form>
{% endblock content %}
for some reason the form.is_valid() method returns False. I have no idea why.
I have tried to use the .errors method on the form and on the form fields. No errors shown.
Thanks for any help!
" Oh! I completely missed that. I think the *args is required because that's how you pass in the request.POST. if you would have an explicit key like myform(data=request.POST) it would have worked because it would be in the *kwargs .. So it was basically failing cause it was acting like you were just initiating a new form, not submitting one –
Nealium
"
I am rendering a form and when I am submitting that form getting this error
IntegrityError at /business/
NOT NULL constraint failed: app_business.user_id
models.py
class business(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=400)
rate_it = models.BooleanField(default=False)
availibility = models.BooleanField(default=True)
def __str__(self):
return self.name
forms.py
class businessform(forms.ModelForm):
class Meta:
model = business
fields = ['name', 'rate_it', 'availibility']
views.py
def formview(request):
if request.method == 'POST':
form = businessform(request.POST)
if form.is_valid():
form.save()
return HttpResponse('saved')
else:
form = businessform
return render(request, 'business.html', {'form':form})
html file
<form method="POST" action="">
{% csrf_token %}
{{form.as_p}}
<input type="submit" name="submit">
</form>
I don't know why this error is coming.
When you are saving the form you haven't passed any user object. Either pass user object while saving the form or make the user field null=True, blank=True in your model.
user = models.ForeignKey(User, null=True, blank=True)
EDIT
Create an user object and save it first. Then pass that instance in the form to update values you got from template. Then save the form.
user = User.objects.create_user(username=username, password=password)
user.save()
obj = business.objects.create(user=user, name="")
form = form = businessform(request.POST, instance=obj)
if form.is_valid():
form.save()
return HttpResponse('saved')
Be careful about the usernames. Usernames must be unique. So, you need to generate those.
I'm trying to upload a file on a model in Django framework.
class banner(models.Model):
#id is made by Django
name = models.CharField(max_length=255)
created_by = models.CharField(max_length=255)
company = models.CharField(max_length=255)
register_date = models.DateField(auto_now_add=True)
file = models.FileField(null=True, blank=True)
file_name = models.CharField(max_length=255)
this is the model:
class BannerForm(forms.Form):
name=forms.CharField(max_length=255)
created_by=forms.CharField(max_length=255)
company=forms.CharField(max_length=255)
data_type=forms.CharField(max_length=255)
register_date=forms.DateField()
file=forms.FileField()
file_name=forms.CharField(max_length=255)
this is the form:
def add_form(request):
form=BannerForm()
last=models.banner.objects.all().last()
if request.method == "POST":
form = forms.BannerForm(request.POST, request.FILES or None)
if form.is_valid():
form.cleaned_data['created_by']
new_banner=models.banner()
new_banner.id=last.id+1
new_banner.name=form.cleaned_data['name']
new_banner.register_date=form.cleaned_data['register_date']
new_banner.company=form.cleaned_data['company']
new_banner.file=form.cleaned_data['file']
new_banner.file_name=new_banner.file.name
new_banner.created_by=form.cleaned_data['created_by']
new_banner.save()
return render(request, "add_banner.html",{"form":form})
this is the view.
Now every time I try to add a banner, I browse the file, but after I click "submit", it is that the file must be chosen, like it doesn't recognize what I browse to the form button.
well you need to specify the upload path in your models
file = models.FileField(null=True, blank=True,upload_to='files')
and make sure you have MEDIA_ROOT and MEDIA_URL defined in your settings.py
in your form
<form method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
...
</form>
You need to include enctype="multipart/form-data" in your form definition.
<form method="post" action="your action" enctype="multipart/form-data">
{% csrf_token %}
...
</form>
Try this something like this :
Models.py :
class banner(models.Model):
#id is made by Django
name = models.CharField(max_length=255)
created_by = models.CharField(max_length=255)
company = models.CharField(max_length=255)
register_date = models.DateField(auto_now_add=True)
file = models.FileField(upload_to='files/', null=True, blank=True)
file_name = models.CharField(max_length=255)
forms.py :
class BannerForm(forms.ModelForm):
class Meta:
model = banner #Or Banner ??
fields = ('name', 'created_by', 'company', 'file', 'file_name' )
views.py :
from myapp.forms import BannerForm
if request.method == "POST":
form = BannerForm(request.POST, request.FILES)
if form.is_valid():
entry = form.save(commit=False)
entry.name = request.POST['name']
entry.created_by = request.POST['created_by']
entry.company = request.POST['company']
entry.file_name = request.POST['file_name']
form.save()
else:
form = BannerForm()
return render(request, "add_banner.html",locals())
And like already said, don't forget :
<form method="POST" action="" enctype="multipart/form-data">
{% csrf_token %}
{{form.name}}
{{form.created_by}}
{{form.company}}
{{form.file_name}}
{{form.file}}
<input type="submit">
</form>
You don't have to specify these things :
new_banner.file=form.cleaned_data['file']
new_banner.register_date=form.cleaned_data['register_date'] -> useless because in your model you set auto_now_add=True, so you don't need te make a field in your HTML form.
Note : if your field created_by = models.CharField(max_length=255) is to put an existing user, so you should make a foreign key field like :
from django.contrib.auth.models import User
created_by = models.ForeignKey(User, verbose_name="Created by")
I want to save an add under the current user that i'm logged in as, but i keep getting the error outlined in the subject.
My models:
class CustomUser(User):
nickname = models.CharField(max_length=255)
phone = models.CharField(max_length=255)
address = models.CharField(max_length=255)
objects = UserManager()
city = models.ForeignKey(locations, unique=False)
def __str__(self):
return self.nickname
class Admin:
pass
class listings(models.Model):
title = models.CharField(max_length=255)
category = models.ForeignKey('category')
description = models.CharField(max_length=255)
published = models.DateField(auto_now=True)
user = models.ForeignKey(CustomUser, unique=False)
def __str__(self):
return self.naslov
class Admin:
pass
The form:
class jobOfferForm(forms.ModelForm):
title = forms.CharField(max_length=255)
description = forms.CharField(max_length=255)
category = forms.ModelChoiceField(queryset=kategorii.objects.all())
class Meta:
model = listings
The template:
<div class="span8">
<form action="" method="POST">
{% csrf_token %}
{{form.as_p}}
<input type="submit" name="submit" value="Save"/>
</form>
</div>
The view!
def displisting(request):
if request.method == 'POST':
form = jobOfferForm(request.POST)
if form.is_valid():
title = form.cleaned_data['title']
description = form.cleaned_data['description']
new_listng = form.save(commit = False)
new_listng.user = request.user
new_listng.object.save()
return HttpResponseRedirect('/listing/review')
else:
form = jobOfferForm()
return render(request,'listings.html',{'form':form,})
I fear the custom user is preventing me from doing that?
But i need the extra attributes?
this error will happen if your user is not logged in.
login using the bundled /admin site and your request.user object will be a valid User instance
request.User isn't an instance of your custom CustomerUser, it's a django.contrib.auth.models.User. Hence the assignment:
new_listng.user = request.user
isn't valid.
You probably want your request.User to be downcast to your CustomerUser (or other subclasses, if you have them). You can add a custom middleware, modeled off django.contrib.auth.middleware.AuthenticationMiddleware that does this.
django-model-util's InheritanceManager has some useful helpers like select_subclasses that make this easy.
I'm using Pinax to create a new project. For this project I needed to create a new app 'Business' which is much like Profiles but they wanted to keep everything seperate for Businesses.
I'm trying to have the admin be able to change the logo or "avatar" for the business profile. Im using the ImageModel class from Photologue to control the image upload, etc but I ran into a problem. When going through the form, the form goes through and redirects but the image doesn't actually get updated. When you go through the django admin, the image uploads fine.
If someone could take a look and see if something is missing, I've been staring at it for too long, so I need a fresh pair of eyes.
Business Models.py
class Business(models.Model):
name = models.CharField(verbose_name="Name", max_length=140)
desc = models.TextField(verbose_name="Description", null=True, blank=True)
bus_type = models.CharField(verbose_name="Business Type", choices=BUSINESS_TYPES, max_length=20)
location = models.CharField(_("location"), null=True, blank=True, max_length=200)
website = models.URLField(_("website"), null=True, blank=True, verify_exists=False)
created_by = models.ForeignKey(User, related_name="Created By")
admin = models.ManyToManyField(User, related_name="Admin User", null=True, blank=True)
followers = models.ManyToManyField(User, related_name="Followed by", null=True, blank=True)
date_added = models.DateField(verbose_name="Date Added")
class Meta:
verbose_name = "Business"
verbose_name_plural = "Businesses"
def __unicode__(self):
return self.name
class BusinessLogo(ImageModel):
business = models.ForeignKey(Business, related_name="Business Association")
My views.py
#login_required
def changeLogo(request, bus_id):
user = request.user
b = get_object_or_404(Business, pk = bus_id)
if request.method == 'POST':
form = ChangeLogoForm(request.POST, request.FILES, instance = b)
if form.is_valid():
biz_logo = form.save(commit=False)
biz_logo.save()
return HttpResponseRedirect('/')
else:
form = ChangeLogoForm()
return render_to_response('business/changelogo.html',
{'user': user, 'form':form, 'b':b}, context_instance=RequestContext(request))
Forms.py
class ChangeLogoForm(ModelForm):
class Meta:
model = BusinessLogo
def save(self, force_insert=False, force_update=False, commit=True):
f = super(ChangeLogoForm, self).save(commit=False)
if commit:
f.save()
print "form save method was called with commit TRUE"
return f
And finally my changelogo.html
...
{% block body %}
<h1>Change Logo</h1>
<form method="POST" action="" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Upload">
</form>
{% endblock %}
...
Thanks everyone, for taking a look.
Steve
The ChangeLogoForm's model is BusinessLogo, but when calling it's constructor you pass it a Business instance:
b = get_object_or_404(Business, pk = bus_id)
...
form = ChangeLogoForm(request.POST, request.FILES, instance = b)
(And you should probably use a OneToOneField field instead of ForeignKey)