NOT NULL constraint failed: dashboard_profile.user_id - python-3.x

I'm trying to save the last IP of User to the Profile module in Django but I get always NOT NULL constraint failed I know that last_ip should be set tonull=True and I run this commands:py .\manage.py makemigrations and py .\manage.py migrate. if you have any suggestions to save IP to the user that will be helpful for me.
Thanks in advance.
#models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(blank=True, max_length=150)
last_ip = models.GenericIPAddressField(null=True, blank=True)
avatar = ContentTypeRestrictedFileField(max_upload_size=10485760, null=True, verbose_name="",default='default.jpg', blank= True, content_types=['image/png', 'image/jpeg'])
def __str__(self):
return self.user.username
#forms.py
class UpdateUserForm(forms.ModelForm):
username = forms.CharField(max_length=150, required=True)
first_name = forms.CharField(max_length=150, required=False)
last_name = forms.CharField(max_length=150, required=False)
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ['username','first_name','last_name','email']
class UpdateAvatarBio(forms.ModelForm):
avatar = forms.ImageField()
bio = forms.CharField()
class Meta:
model = Profile
fields = ['avatar', 'last_ip', 'bio']
#views.py
def ip_client(request):
return (
x_forwarded_for.split(',')[0]
if (x_forwarded_for := request.META.get('HTTP_X_FORWARDED_FOR'))
else request.META.get('REMOTE_ADDR')
)
def profile(request):
ip = ip_client(request)
model = Profile(last_ip=ip)
model.save() # Traceback suppose here is the issue
if request.method == 'POST':
...
...
return render(request, 'profile.html', {'user_form': user_form, 'profile_form': profile_form})

You didn't add the user to Profile before saving it
def profile(request):
ip = ip_client(request)
model = Profile(last_ip=ip)
moddl.user=request.user #Add this
model.save() # Traceback suppose here is the issue
if request.method == 'POST':
...
...
return render(request, 'profile.html', {'user_form': user_form, 'profile_form': profile_form})
Edit:
Since the user is OneToOne (which means it is a the primary key), so Your code shall be like this
def profile(request):
ip = ip_client(request)
profile = Profile.objects.get(user=request.user)
profile.last_ip = ip
profile.save()
if request.method == 'POST':
...
...
return render(request, 'profile.html', {'user_form': user_form, 'profile_form': profile_form})

Related

how to post data in a nested serializer in Django rest framework

I am working on an app and need help I want to authenticate LinkedIn and save the access token in a table and then collect the LinkedIn user details in another table below is my model.py
class LinkedInUserCode(models.Model):
"""
Credentials for the user to give access to LinkedIn.
"""
user = models.OneToOneField(User, on_delete=models.CASCADE)
token = models.CharField(max_length=1024)
expires_in = models.IntegerField()
def __str__(self):
return f'{self.token}'
class Meta:
db_table = 'linkedin_user_code'
verbose_name_plural = "LinkedIn User Codes"
class LinkedInProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
linkedin_id = models.CharField(max_length=1024, blank=True, null=True)
first_name = models.CharField(max_length=1024, blank=True, null=True)
last_name = models.CharField(max_length=1024, blank=True, null=True)
profile_image_url = models.CharField(max_length=1024, blank=True, null=True)
date_created = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
def __str__(self):
return f'{self.linkedin_id}'
class Meta:
db_table = 'linkedin_profile'
verbose_name_plural = "LinkedIn Profiles"
I am using a nested serializer and this is my serialiser
class LinkedInProfileSerializer(ModelSerializer):
"""
Serializer for the LinkedInProfile model.
"""
id = IntegerField(required=False)
user = ReadOnlyField(source='user.email')
linkedin_access = ReadOnlyField(source='linkedin_access.token')
class Meta:
model = LinkedInProfile
fields = '__all__'
def create(self, validated_data):
"""
Create a new LinkedInProfile instance.
"""
return LinkedInProfile.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.linkedin_id = validated_data.get('linkedin_id')
instance.first_name = validated_data.get('first_name')
instance.last_name = validated_data.get('last_name')
instance.profile_image_url = validated_data.get('profile_image_url')
instance.linkedin_access = validated_data.get('linkedin_access')
instance.save()
return instance
class LinkedInUserCodeSerializer(ModelSerializer):
user = ReadOnlyField(source='user.email')
profiles = LinkedInProfileSerializer(many=True, read_only=True)
class Meta:
model = LinkedInUserCode
fields = ['user', 'token', 'expires_in', 'profiles']
def create(self, validated_data):
""" Create and return necessary credentials for linkedin."""
profile = validated_data.pop('profiles')
access_token = LinkedInUserCode.objects.create(**validated_data)
for profile_data in profile:
LinkedInProfile.objects.create(linkedin_access=access_token, **profile_data)
return access_token
def update(self, instance, validated_data):
profiles = validated_data.pop('profiles')
instance.token = validated_data.get('token', instance.token)
instance.expires_in = validated_data.get('expires_in', instance.expires_in)
instance.save()
temp_profile = []
existing_ids = [profiles.get('linkedin_id') for profile in instance.profiles.all()]
for profile_data in profile:
if profile_data.get('linkedin_id') in existing_ids:
temp_profile.append(LinkedInProfile.objects.get(linkedin_id=profile_data.get('linkedin_id')))
else:
temp_profile.append(LinkedInProfile.objects.create(linkedin_access=instance, **profile_data))
instance.profiles.set(temp_profile)
for profile in instance.profiles.all():
if profile not in temp_profile:
profile.delete()
return instance
I have written a script that I am using to make requests to the LinkedIn api and here is my view I want to populate it at once any idea how I can go about it I keep having issues with the foreign key of LinkedIn_access
class LinkedInCallbackAPIView(APIView):
"""
This View is used to get and save the Access Token from LinkedIn authorization page.
"""
def get(self, request, *args, **kwargs):
response = request.GET
if response is not None and state != response.get('state'):
return Response({'error': "Invalid state"}, status=status.HTTP_401_UNAUTHORIZED)
else:
queryset = LinkedInUserCode.objects.filter(user=request.user)
code = response.get('code')
access_token = linkedin.get_access_token(code)
profile = linkedin.get_user_profile(access_token.get('access_token'))
profile = {
'linkedin_id': profile.get('id'),
'first_name': profile.get('firstName').get('localized').get('en_US'),
'last_name': profile.get('lastName').get('localized').get('en_US'),
'profile_image_url': profile.get('profilePicture').get('displayImage'),
}
data = {
'token': access_token.get('access_token'),
'expires_in': access_token.get('expires_in'),
'user': request.user,
'profiles': profile,
}
serializer = LinkedInUserCodeSerializer(data=data)
if queryset.exists():
serializer.update(queryset.first(), data)
return Response({'message': 'Your LinkedIn user Access Token was Updated'},status=status.HTTP_200_OK)
if serializer.is_valid():
serializer.save(**data)
# there will be a return response here
I need help passing this table and not using a single table for it
thank you

The email address of participant is added to all meetings, not just the one he joined. Django

Followed the tutorial on creating meetups and allow participants join them. When adding a participant (his email address) using the form, the email address is added to all meetings, not just the one he joined. I am new to Django, but it seems like the problem is in the ManyToMany relationship.
Models.py
from django.db import models
class Location(models.Model):
name = models.CharField(max_length=200)
address = models.CharField(max_length=300)
def __str__(self):
return f'{self.name} ({self.address})'
class Participant(models.Model):
email = models.EmailField(unique=True)
def __str__(self):
return self.email
class Meetup(models.Model):
title = models.CharField(max_length=200)
organizer_email = models.EmailField()
date = models.DateField()
slug = models.SlugField(unique=True)
description = models.TextField()
image = models.ImageField(upload_to='images')
location = models.ForeignKey(Location, on_delete=models.CASCADE)
participants = models.ManyToManyField(Participant, blank=True)
def __str__(self):
return f'{self.title} - {self.slug}'
Views.py
from django.shortcuts import render, redirect
from .models import Meetup, Participant
from .forms import RegistrationForm
# Create your views here.
def index(request):
meetups = Meetup.objects.all()
return render(request, 'meetups/index.html', {
'meetups': meetups
})
def meetup_details(request, meetup_slug):
try:
selected_meetup = Meetup.objects.get(slug=meetup_slug)
if request.method == 'GET':
registration_form = RegistrationForm()
else:
registration_form = RegistrationForm(request.POST)
if registration_form.is_valid():
user_email = registration_form.cleaned_data['email']
participant, _ = Participant.objects.get_or_create(email=user_email)
selected_meetup.participants.add(participant)
return redirect('confirm-registration', meetup_slug=meetup_slug)
return render(request, 'meetups/meetup-details.html', {
'meetup_found': True,
'meetup': selected_meetup,
'form': registration_form
})
except Exception as exc:
return render(request, 'meetups/meetup-details.html', {
'meetup_found': False
})
def confirm_registration(request, meetup_slug):
meetup = Meetup.objects.get(slug=meetup_slug)
return render(request, 'meetups/registration-success.html', {
'organizer_email': meetup.organizer_email
})
Forms.py
from django import forms
class RegistrationForm(forms.Form):
email = forms.EmailField(label='Your email')

How to get a value of foreign key between apps of Django?

If somebody has this kind of issue, answer is below, did it :)
I have two apps (accounts and company).
accounts/models.py
class Organization(models.Model):
organization_name = models.CharField(max_length=20)
#custom user model
class NewUser(AbstractBaseUser):
which_organization = models.ForeignKey(Organization, on_delete = models.CASCADE, null=True, blank=True)
#other fields
company/models.py
from accounts import models as accounts_model
class Branch(models.Model):
branch_name = models.ForeignKey(
accounts_model.Organization, on_delete = models.CASCADE, null=True, blank=True)
#other fields
company/forms.py
from .models import Branch
class BranchForm(forms.ModelForm):
class Meta:
model = Branch
fields = '__all__'
company/views.py
from .forms import BranchForm
def some_function(request):
form = BranchForm()
if request.method == 'POST':
form = BranchForm(request.POST, request.FILES)
if form.is_valid():
form.save(commit=False)
form.branch_name = request.user.which_organization
print("User organization: ", request.user.which_organization)
form.save()
return render(request, 'company/index.html', {'form': form})
P.s. Everything works well. I am able to print the user's organization with
print("User organization : ", request.user.which_organization)
But cannot save it with
form.branch_name = request.user.which_organization
in views.py. Instead of getting exact organization name of the user, created object lists all organization names...
How to achieve it?)
Did it :D
def some_function(request):
form = BranchForm()
if request.method == 'POST':
form = BranchForm(request.POST, request.FILES)
if form.is_valid():
another_form = form.save(commit=False)
another_form.branch_name = Organisation.objects.get(id= request.user.which_organization.id )
new_form.save()
return render(request, 'company/index.html', {'form': form})
Try passing an instance of the Organisation model,
def some_function(request):
form = BranchForm()
if request.method == 'POST':
form = BranchForm(request.POST, request.FILES)
if form.is_valid():
form.save(commit=False)
organisation_instance = Organisation.objects.get(id = request.user.which_organization.id )
form.branch_name = organisation_instance
print("User organization: ", request.user.which_organization)
form.save()
return render(request, 'company/index.html', {'form': form})

How to overwrite data from a model that is linked to the main model through a o-t-m relationship?

I have three models that are related to each other, namely:
models.py
class Shop(models.Model):
number = models.PositiveSmallIntegerField()
name = models.CharField(db_index=True)
city = models.ForeignKey(ShopCity, on_delete=models.CASCADE)
class Product(models.Model):
name = models.CharField(db_index=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
class ProductQuantity(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
shop = models.ForeignKey(Shop, on_delete=models.CASCADE)
quantity = models.PositiveSmallIntegerField(default=None)
In the admin panel they are linked in this way:
admin.py
class ProductQuantityInline(admin.TabularInline):
model = ProductQuantity
extra = 0
#admin.register(Product)
class ProductAdmin(ImportExportActionModelAdmin):
fields = ['name', 'price']
list_display = ['name', 'price']
inlines = [ProductQuantityInline]
There is a need to overwrite data with REST API
serializers.py
class QuantitySerializer(serializers.ModelSerializer):
class Meta:
model = ProductQuantity
fields = ('shop', 'quantity')
class ProductSerializer(serializers.ModelSerializer):
productquantity = serializers.SerializerMethodField(read_only=False)
class Meta:
model = Product
fields = ('name', 'price', 'productquantity')
def get_productquantity(self, obj):
return [QuantitySerializer(s).data for s in obj.productquantity_set.all()]
And finally my handler for REST API:
views.py
#api_view(['GET', 'PATCH', 'PUT', 'DELETE'])
def api_product_detail(request, pk):
product = Product.objects.get(pk=pk)
if request.method == 'GET':
serializer = ProductSerializer(product)
return Response(serializer.data)
elif request.method == 'PUT' or request.method == 'PATCH':
serializer = ProductSerializer(product, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
product.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
As a result, data such as the name and price are overwritten, and the productquantity is not overwritten.
What am I doing wrong? Thanks for any help.

Getting the post instance in Django class based views

I currently use a function based view to let users write comments on posts, but I'm trying to convert it to class based views
Function views.py
def comment(request, pk):
form = CommentForm(request.POST)
# Post instance
post_instance = get_object_or_404(Post, pk=pk)
if request.method == 'POST':
if form.is_valid:
obj = form.save(commit=False)
obj.commenter = request.user
obj.post = post_instance
obj.save()
return redirect('/')
else:
messages.error(request, 'Comment Failed')
return render(request, 'comment.html', {'form': form})
Class views.py
class CommentView(FormView):
template_name = 'comment.html'
form_class = CommentForm
success_url = '/'
def get_object(self):
pk = self.kwargs.get('pk')
post_instance = get_object_or_404(Post, pk=pk)
return post_instance
def form_valid(self, form):
obj = form.save(commit=False)
obj.commenter = self.request.user
obj.post = post_instance
obj.save()
return super().form_valid(form)
I'm trying to implement the same logic for saving the comment but I get the error: name 'post_instance' is not defined
get_object() is returning the 'post_instance' variable but I can't access it.
Could you guys show me where I'm doing a mistake, thanks in advance!
You can try:
class CommentView(FormView):
template_name = 'comment.html'
form_class = CommentForm
success_url = '/'
def get_object(self):
pk = self.kwargs.get('pk')
post_instance = get_object_or_404(Post, pk=pk)
return post_instance
def form_valid(self, form):
obj = form.save(commit=False)
obj.commenter = self.request.user
obj.post = self.get_object()
obj.save()
return super().form_valid(form)

Resources