IntegrityError at * NOT NULL constraint failed: main_post.owner_id - django

I want to create a PostModel(just like instagram) and while the form is created to connect the user to the model with One-to-one/foreign key relationship, anyway I'm getting a problem while trying to upload an image and the db doesn't updates.
I've tried this solution
...
# models.py
from django.contrib.auth.models import User
from django.conf import settings
class Post(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
description = models.CharField(max_length=255, blank=True)
image = models.ImageField(upload_to='images')
uploaded_at = models.DateTimeField(auto_now_add=True)
...
# forms.py
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('description', 'image', )
def save(self, commit=True):
if commit:
Post.save()
return Post
...
# views.py
def account(request):
post = PostForm(request.POST, request.FILES)
if request.method == "POST":
if post.is_valid():
post.save(commit=False)
post.owner = request.user
post.save(commit=True)
messages.success(request, f"you had successfully updated your profile image")
return redirect("main:account")
else:
for msg in form.error_messages:
messages.error(request, f"{msg}: {form.error_messages[msg]}")
return render(request = request,
template_name = "main/account.html",
context={'PostForm':post})
post = PostForm()
return render(request = request,
template_name = "main/account.html",
context={'PostForm':post})

You should not override the def save() method, this is fine as it is now, so:
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('description', 'image', )
# no save
as for the view, you need to add the owner to the object, but here you are adding it to the form, and that thus has no effect (on the object):
from django.contrib.auth.decorators import login_required
#login_required
def account(request):
post = PostForm(request.POST, request.FILES)
if request.method == 'POST':
if post.is_valid():
post.instance.owner = request.user
post.save()
messages.success(request, f'you had successfully updated your profile image')
return redirect('main:account')
# …
I would also advise to rename post to post_form, since this is a form, not a post object.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].

Related

Cross queries in django

I have two models as below
class Watched(Stamping):
user = models.ForeignKey("User", null=True, blank=True, on_delete=models.CASCADE,
default=None)
count = models.PositiveIntegerField()
class Link(Stamping):
...
user = models.ForeignKey(User, on_delete=models.CASCADE, default=None)
url = models.CharField(max_length=256, default=None)
watched = models.ForeignKey(Watched, null=True, blank=True, on_delete=models.CASCADE, default=None)
...
My forms.py
class SimpleLink(forms.Form):
url = forms.URLField(max_length=256)
A user can create a Link object and when some conditions are met, the object will be added to Watched. The Watched model contains objects created by different users.
Now I want to filter the Watched class and grab only the objects created by the requesting user in the Link model but I don't know how I can achieve that. Any help will be appreciated.
A sample of what I want to achieve is...
Watched.objects.filter(Link.objects.filter(user=request.user). I know my sample is crazy. But from the outside query, I want to grab the Link objects created by user making the request
You need to limit the queryset in your ModelForm. A ModelForm will thus look like:
from django import forms
class LinkForm(forms.ModelForm):
def __init__(self, *args, user=None, **kwargs):
super().__init__(*args, **kwargs)
if user is not None:
self.fields['watched'].queryset = Watched.objects.filter(
link__user=user
)
class Meta:
model = Link
fields = ['url', 'watched']
In our view, we can then set the user object:
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect, render
#login_required
def some_view(request):
if request.method == 'POST':
form = LinkForm(request.POST, user=request.user)
if form.is_valid():
form.instance.user = request.user
form.save()
return redirect('name-of-some-form')
else:
form = LinkForm(user=request.user)
return render(request, 'some-template.html', {'form': form})
For a class-based view, we can override the .get_form_kwargs(…) method [Djangod-doc]:
from django.contrib.auth.mixins import LoginRequiredMixin
class SomeView(LoginRequiredMixin, CreateView):
form_class = LinkForm
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)

Send the logged user Profile Model to a CreateView form

what I am trying to accomplish is to send the "requester" model, using the logged-in user to a form ...
Mainly the problem that I have is that the views.py "class CreateOrderView(CreateView)" does not have a parameter "request" , so I cannot get the request.user, and therefore get requester_obj and automatically select this requester_obj in the form field "requester", when entering this page.
models.py Order:
DEFAULT_REQUESTER_ID= 1
requester = models.ForeignKey(Profile, on_delete=models.CASCADE, default=DEFAULT_REQUESTER_ID, verbose_name="usuario")
forms.py:
class OrderCreateForm(BaseForm, forms.ModelForm):
date = forms.DateField(label="Fecha" , widget=forms.DateInput(attrs={'type': 'date'}))
class Meta:
model = Order
fields = ['requester','title' , 'date', ]
views.py:
#method_decorator(staff_member_required, name='dispatch')
class CreateOrderView(CreateView):
template_name = 'form.html'
form_class = OrderCreateForm
model = Order
def get_success_url(self):
self.new_object.refresh_from_db()
return reverse('update_order', kwargs={'pk': self.new_object.id})
def form_valid(self, form):
object = form.save()
object.refresh_from_db()
self.new_object = object
return super().form_valid(form)
I get the requester like this:
#login_required
def create(request):
#return render(request, 'app_client/create.html')
if request.method == 'POST':
if request.POST['value'] and request.POST['products']:
logged_user = request.user
user_obj = get_object_or_404(User, username=logged_user)
requestor_obj = get_object_or_404(Profile, user=user_obj)
....
I just found a solution for my issue...
What I did was to remove the "requester" field in forms.py, and send the requester obj to the form after user presses the submit form button
def form_valid(self, form):
logged_user = self.request.user
user_obj = get_object_or_404(User, username=logged_user)
requester_obj = get_object_or_404(Profile, user=user_obj)
form.instance.requestor = requestor_obj
object = form.save()
object.refresh_from_db()
self.new_object = object
return super().form_valid(form)
form.instance.requestor = requestor_obj was the line that I needed to send it to form before saving it.
ref: Django CreateView Foreign key

Save form data to database

I am new in Django and I really need help,
I do not know how to save my form data to database. I have problem to views.py
I will user's id who filled the form added into the foreign key field.
If there is any link or example that help me I appreciate you.
# views.py
#login_required(login_url="home")
def melk_new(request):
form = MelkForm()
???
return render(request, 'melk_new.html',{'form': form})
# models.py
class Melk(models.Model):
category = models.CharField(max_length=50)
city = models.CharField(max_length=100)
person = models.ForeignKey('CustomUser', on\_delete=models.CASCADE)
def \_\_str\_\_(self):
return self.category
class CustomUser(AbstractUser):
def __str__(self):
return self.email
---------------------------------------------------------------------------
# forms.py
class MelkForm(forms.ModelForm):
class Meta:
model = Melk
fields = ('category', 'city')
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm):
model = CustomUser
fields = ('username', 'email')
To get the currently logged in user you'll find it within request.user object. but before you assume that there is a currently logged in user, you need to validate that so you have 2 widely known options:
request.user.is_authenticated()
#login_required() decorator used if you from django.contrib.auth.decorators import login_required
if request.user.is_authenticated():
Car.objects.create(model_id=some_id, person=request.user)
Note:
The #login_required() is added above the function
#login_required(login_url="home")
def melk_new(request):
form = MelkForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.user_id = request.user.id
instance.save()
return render(request,'melk_new.html', { 'form': form})

Associating the logged in user with the Photo Model

I basically want to associate the logged in user name with the PhotoModel by using models.ForeignKey. I override the safe_model in admin.py but when i execute the views.py class PhotoCreateNew(View) then it stops at print(form) and the form is not validated (if form.is_valid()) skips the entire part which was supposed to set the request.user as photo.user_name and return the empty template.
My models.py
class Photo(models.Model):
user_name = models.ForeignKey(User, on_delete=models.CASCADE)
PLACES = (('RD','研发-R&D'),('Warehouse','仓库-Warehouse'),('Gate','门卫处-Gate Guard'),('SecondFloor','2F生产部'))
photo = models.FileField()
photo_name = models.CharField(max_length=20)
date = models.DateField(auto_now="True")
quantity = models.CharField(max_length=4)
CONDITIONS = (('N','NG'), ('G', 'GOOD'))
condition =models.CharField(max_length=1,choices=CONDITIONS)
place = models.CharField(max_length=30,choices=PLACES,default='Warehouse')
def __str__(self):
return self.photo_name
def get_absolute_url(self):
return reverse('photo:photo_detail', kwargs={'pk':self.pk})
class PhotoForm(ModelForm):
class Meta:
model = Photo
fields =['user_name','photo','photo_name','quantity','condition','place']
exclude= ('user_name',)
My admin.py:
from django.contrib import admin
from photo.models import Photo
from photo.models import Supplier
class PhotoAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
if not obj.pk:
obj.user_name = request.user
obj.save()
admin.site.register(Supplier,)
admin.site.register(Photo, PhotoAdmin)
My views.py:
class PhotoCreateNew(View):
form_class = PhotoForm
template_name = 'photo/photo_form.html'
def get(self, request):
form =self.form_class(None)
return render(request, self.template_name, {'form':form})
def post(self,request):
form = self.form_class(request.POST)
print(request.user)
print(form)
if form.is_valid(): # uploader has been excluded. No more error.
print("Przeszlo")
photo = form.save(commit=False) # returns unsaved instance
photo.user_name = request.user
print(request.user)
photo.save() # real save to DB.
return redirect('photo:photo_detail')
return render(request,self.template_name,{})
After initializing the form class with request.POST and request.FILES it is working.
I had to replace :
form = self.form_class(request.POST)
with :
form = self.form_class(request.POST, request.FILES)

ValueError at /new_topic/ Cannot assign "<SimpleLazyObject: <django......>": "Topic.owner" must be a "User" instance

*Any time i insert data the above error occurred! *
# my views
def new_topic(request):
"""Add a new topic."""
if request.method != 'POST':
# No data submitted; create a blank form.
form = TopicForm()
else:
# POST data submitted; process data.
form = TopicForm(request.POST or None, request.FILES or None)
if form.is_valid():
new_topic = form.save(commit=False)
new_topic.owner = request.user #this where i think, i'm messing up!
new_topic.save()
return HttpResponseRedirect(reverse('learning_logs:topics'))
context = {'form': form}
return render(request, 'learning_logs/new_topic.html', context)
*model representing each Topic *
from django.contrib.auth.models import User
def upload_location(instance, filename):
return "%s/%s" %(instance.id, filename)
class Topic(models.Model):
"""A topic the user is learning about"""
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
image = models.ImageField()
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
owner = models.ForeignKey(User)
def __str__(self):
"""Return a string representation of the model."""
return self.text
Any help please!
Setting new_topic.owner = request.user should be fine if the user is logged in. However if the user is not logged in, then trying to assign an anonymous user would cause problems.
You can prevent this by using the login_required decorator, so that only logged-in users can access the view.
#login_required
def new_topic(request):
...