Cascade delete not working with django models - django

I have been using a Video model related with the user on a cascade basis.
from django.conf import settings
class Video(models.Model):
uuid = models.CharField(max_length=255, default="")
title = models.CharField(max_length=255, default="")
description = models.CharField(max_length=5000, default="")
privacy = models.CharField(max_length=10, default="public")
category = models.CharField(max_length=50, default="General")
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=None)
def delete(self, *args, **kwargs):
publisher = pubsub_v1.PublisherClient()
topic_name = '...'
message_to_publish = self.path
publisher.publish(topic_name, data=message_to_publish.encode('utf-8'), spam='eggs')
logging.info("Sending pubsub to delete folder : {0}".format(message_to_publish))
super(Video, self).delete(*args, **kwargs)
When I trigger a delete on the user,
def clear_user(request):
user = request.user
user.delete()
This does not trigger the overloaded delete function. How can I achieve that overloaded delete function to be called on user delete?

because the related objects are deleted with sql in database directly, it do not call the delete method of the related model, so it does not work to override delete method. it could be one way to use pre_delete or post_delete signal.
# signals.py
from django.db.models.signals import pre_delete
from django.dispatch import receiver
from django.contrib.auth import get_user_model
User=get_user_model()
#receiver(pre_delete, sender=User)
def user_delete_callback(sender, **kwarg):
# do something
print('user delete callback:', kwarg)
# apps.py
from django.apps import AppConfig
class MyAppConfig(AppConfig):
name = 'myapp'
def ready(self):
from . import signals

Related

Using signals in django, trying to generate code for SMS verification but generated code is not visible in admin. what am i missing?

folder structure
enter image description here
models.py from face_detect
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Profile(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE,null=True)
mobile = models.CharField(max_length=10,null=True)
add = models.CharField(max_length=10,null=True)
image = models.FileField(null=True)
def __str__(self):
return self.user.username
models.py from otp
from django.db import models
from django.contrib.auth.models import User
from face_detect.models import Profile
import random
# Create your models here.
class Code(models.Model):
number = models.CharField(max_length=5, blank=True)
user = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self):
return str(self.number)
#otp verification
def save(self, *args, **kwargs):
number_list = [x for x in range(10)]
code_items = []
for i in range(5):
num = random.choice(number_list)
code_items.append(num)
code_string = "".join(str(item) for item in code_items)
self.mobile = code_string
super().save(*args,**kwargs)
signals.py from otp
from face_detect.models import Profile
from django.contrib.auth.models import User
from .models import Code
from django.db.models.signals import post_save
from django.dispatch import receiver
#receiver(post_save, sender=User)
def post_save_generate_code(sender, instance, created, *args, **kwargs):
if created:
Code.objects.create(user=instance)
apps.py from otp
from django.apps import AppConfig
class OtpConfig(AppConfig):
name = 'otp'
def ready(self):
import otp.signals
init.py from otp
default_app_config = 'otp.apps.OtpConfig'
admin.py from otp
from django.contrib import admin
from .models import Code
# Register your models here.
admin.site.register(Code)
code seen in http://127.0.0.1:8000/admin/otp/code/
enter image description here
code is not visible.
how can i make the code visible so i can use it for otp verification while login.
Thanks in advance
In admin page you will see the __str__ method, so there seems to be nothing wrong with your code most probably your code instance's value is "", Also one other thing
def __str__(self):
return str(self.number)
you dont need to cast it to str here its already char field
and another thing is here:
def __str__(self):
return self.user.username
in Profile model you made user nullable so this means not all the profile instances might not have user so you will get NoneType has no attribute username
change it to this to prevent this errors:
def __str__(self):
return self.user.username if self.user else ""

Django Signals set signal to create a default avatar image on UserExtended model after registering User

I want to create an entry on UserExtended model after registering an user on Django default user model.
here is UserExtended model:
class UserExtended(models.Model):
extended_id = models.AutoField(primary_key=True, editable=False)
avatar = models.ImageField(null=True, blank=True, default='Capture.PNG')
user = models.OneToOneField(User, on_delete=models.CASCADE, null=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
here is the view function that registering the user
#api_view(['POST'])
def register_user(request):
data = request.data
user = User.objects.create(
first_name=data['name'],
username=data['username'],
email=data['email'],
password=make_password(data['password'])
)
serializer = UserSerializerWithToken(user, many=False)
return Response(serializer.data)
here is the serializer
class UserSerializer(serializers.ModelSerializer):
name = serializers.SerializerMethodField(read_only=True)
isAdmin = serializers.SerializerMethodField(read_only=True)
avatar = serializers.SerializerMethodField()
def get_avatar(self, obj):
avatar = obj.userextended.avatar.url
print(avatar)
if avatar == '':
avatar = 'null'
return avatar
class Meta:
model = User
fields = ['id', 'username', 'email', 'name', 'avatar', 'isAdmin']
def get_name(self, obj):
name = obj.first_name
if name == '':
name = obj.email
return name
def get_isAdmin(self, obj):
return obj.is_staff
class UserSerializerWithToken(UserSerializer):
token = serializers.SerializerMethodField(read_only=True)
class Meta:
model = User
fields = ['id', 'username', 'email', 'name', 'isAdmin', 'token']
here is the signal.py:
from django.db.models.signals import post_save, pre_delete
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import UserExtended
#receiver(post_save, sender=User)
def create_user_extended(sender, instance, created, **kwargs):
if created:
UserExtended.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_extended(sender, instance, **kwargs):
instance.userextended.save()
but the signal is not working to create an default avatar file for an new registered user
I am new. Please help me.
Django does not look for any file named signal.py, etc. by default. Hence what is happening it that your signals are never registered (in fact the file you write them in is never run). The general solution to adding signals is to write them in a separate file and then import / register them in the app config's ready method.
In the app in which you write signal.py there should be a file apps.py in which there should be a class inheriting from AppConfig edit this class and add a ready method to it and import your signals there:
from django.apps import AppConfig
# The parts marked as "Don't edit" mean to keep them as it already is in _your_ code and not copy it
class YourAppConfig(AppConfig): # Don't edit
default_auto_field = 'django.db.models.BigAutoField' # Don't edit
name = 'your_app' # Don't edit
# Copy only the code below
def ready(self):
# models, signals etc. are imported only here because otherwise the models might not be loaded yet
from . import signal

Create a social authentication functionality with google django

Hello I am a newbie and have a task to do,I have tried simple social authentication that is working but below is bit complicated:
Create a social authentication functionality with google and add user in a
database. After adding user in a database, customer should also be created
using django signals.
Note:- Customer is one to one related with user?
My models.py :
class Buddy(models.Model):
user_name=models.CharField(max_length=200,blank=True,null=True)
def __str__(self):
return str(self.user_name)
class Customer(models.Model):
customer_name=models.OneToOneField(Buddy,
on_delete = models.CASCADE,
blank=True,null=True)
def __str__(self):
return str(self.customer_name)
My settings.py includes the following lines:
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '2377[...].apps.googleusercontent.com'
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = '[...]'
SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = ['email']
INSTALLED_APPS = [ ... # oauth
'oauth2_provider',
'social_django',
'rest_framework_social_oauth2' ]
AUTHENTICATION_BACKENDS = ( # Google OAuth2
'social_core.backends.google.GoogleOAuth2',
# django-rest-framework-social-oauth2
'rest_framework_social_oauth2.backends.DjangoOAuth2', # Django
'django.contrib.auth.backends.ModelBackend', )
You have to use Django's post_save signal.
In your models.py have:
class Buddy(models.Model):
user_name=models.CharField(max_length=200, blank=True, null=True)
def __str__(self):
return str(self.user_name)
class Customer(models.Model):
# This translates into buddy_id when you migrate
buddy=models.OneToOneField(Buddy,on_delete = models.CASCADE,
blank=True, null=True)
customer_name = models.CharField(max_length=200, blank=True, null=True)
def __str__(self):
return str(self.customer_name)
In your views.py make sure you have
from django.shortcuts import render
from django.db.models.signals import post_save
from .models import Buddy
from .callbacks import save_customer
# You'll customize this view to read any parameters and provide user_name
def custom_view(request):
Buddy.objects.create(user_name="SomeUsername")
# Any of your other logic comes here, specify in the dict
return render(request, 'yourpage.html', {})
# This should be at the bottom of your views.py:
post_save.connect(save_customer, sender=Buddy)
Then create a new file in the same location called callbacks.py and there include:
from .models import Buddy
from django.db.models.signals import post_save
from django.dispatch import receiver
#receiver(post_save, sender=Buddy)
def save_customer(sender, instance, **kwargs):
# Customize your OneOnOne model on a meaningful way so it will be useful
customer = Customer.objects.create(customer_name=instance.user_name)
instance.customer = customer
instance.customer.save()
Read more about Django signals here.

I cannot save a picture link from a facebook account

I am trying get a picture link from a facebook account but get this message:
django.db.utils.IntegrityError: UNIQUE constraint failed:
user_profile.user_id
I can see a picture link in console, but I cannot save it in user profile.
here is my model.py when I'm trying to do that.
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from allauth.account.signals import user_signed_up, user_logged_in
from allauth.socialaccount.models import SocialAccount
import hashlib
try:
from django.utils.encoding import force_text
except ImportError:
from django.utils.encoding import force_unicode as force_text
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,
related_name='userprofile')
city = models.CharField(max_length=30, blank=True)
about = models.TextField(blank=True)
avatar = models.ImageField(upload_to='avatars/', verbose_name='Images',
blank=True)
sound = models.BooleanField(default=False)
points = models.DecimalField(max_digits=4, decimal_places=2, default=0.00)
energy = models.IntegerField(default=0)
avatar_url = models.URLField(max_length=500, blank=True, null=True)
class Meta:
db_table = 'user_profile'
verbose_name = 'Profile'
verbose_name_plural = 'Profiles'
def __str__(self):
return str(self.user)
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.userprofile.save()
##receiver(user_logged_in)
#receiver(user_signed_up)
def set_initial_user_names(request, user, sociallogin=None, **kwargs):
preferred_avatar_size_pixels = 25
if sociallogin:
if sociallogin.account.provider == 'facebook':
picture_url = "http://graph.facebook.com/{0}/picture?width={1}&height={1}".format(
sociallogin.account.uid, preferred_avatar_size_pixels)
profile = UserProfile(user=user, avatar_url=picture_url)
#profile = UserProfile.objects.get(user=user)
#profile.avatar_url = picture_url
profile.save()
If I am doing like that at the end:
#profile = UserProfile(user=user, avatar_url=picture_url)
profile = UserProfile.objects.get(user=user)
profile.avatar_url = picture_url
profile.save()
I am not gettin any message in the console, but user profile doesn't save.
This line profile = UserProfile(user=user, avatar_url=picture_url) is causing the problem as you are trying to create a new instance of profile which already exists. The profile becomes unique because of OneToOne field in your UserProfile model.
And you don't need to get the user from the database because set_initial_user_names function is already passing the registered user to you as a parameter. So just do user.userprofile. Then you can just update the user with new information.
Also I would suggest you to download the picture from the url provided and then save it in your image field of your model like this:
import urllib
from django.core.files import File
# for python 2: result = urllib.urlretrieve(picture_url)[0]
result = urllib.request.urlretrieve(picture_url)[0] # for python 3
user.userprofile.avatar.save('test.jpg', File(open(result, 'rb')))
user.userprofile.save()

How can I implement built in signals, for my app?

I have a project myappointments, with two apps- appointments and clinic in it.
Objective:
When a user logins, details should be entered in the database.
appointments/models.py:
class Event(models.Model):
id=models.AutoField(primary_key=True, unique=True)
type=models.CharField(max_length=60)
description = models.CharField(max_length=150)
time = models.DateTimeField(default=timezone.now)
appointments/init.py:
default_app_config = 'appointments.apps.AppointmentsConfig'
appointments/apps.py:
from django.apps import AppConfig
class AppointmentsConfig(AppConfig):
name = 'appointments'
def ready(self):
import appointments.signals
appointments/signals.py:
from django.contrib.auth.signals import user_logged_in
from django.dispatch import receiver
def record_loggedin(sender, user, request, **kwargs):
ev = Event(type="Login", description = 'User logged in: {}'.format(request.user.id))
ev.save()
print("User has logged in. Saved event to DB.")
user_logged_in.connect(record_loggedin)
What other modifications do I need to do this?