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

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?

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 ""

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.

Cascade delete not working with django models

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

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()

Having problems with a query in Django

I'm building my first app within Django and I'm trying to query a "load" based on the company that i've attached to the load. Here's the model in question.
class Load(models.Model):
company = models.ForeignKey(UserCompany, null=True,
on_delete=models.CASCADE)
load_number = models.IntegerField()
carrier = models.CharField(max_length=255)
pickup_date = models.DateField()
delivery_date = models.DateField()
shipper = models.CharField(max_length=255)
consignee = models.CharField(max_length=255)
po_number = models.CharField(max_length=255)
pu_number = models.CharField(max_length=255)
pieces = models.IntegerField()
description = models.TextField()
date_created = models.DateTimeField(blank=True, null=True)
def publish(self):
self.date_created = timezone.now()
self.save()
def __str__(self):
return str(self.load_number)
Now I'm trying to display a list on a page, but only display the loads attached to a specific company. The user needs to be attached to that company as well so here are my user models.
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class UserCompany(models.Model):
company_name = models.CharField(max_length=200)
def __unicode__(self):
return self.company_name
def __str__(self):
return self.company_name
# User Model
class UserProfileInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
# Additional Classes
profile_pic = models.ImageField(upload_to='profile_pics',
blank=True)
company = models.ForeignKey(UserCompany,
null=True,on_delete=models.CASCADE)
def __str__(self):
return self.user.username
Then i'm trying to query the "loads" within this view.
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.shortcuts import render, get_object_or_404
from django.shortcuts import redirect
import datetime
from django.conf import settings
from django.utils import timezone
from django.http import HttpResponse
from django.views.generic import View, DetailView
from easy_pdf.views import PDFTemplateResponseMixin
from loads.models import Load
from .forms import LoadForm
from users.models import UserCompany, UserProfileInfo
# Create your views here.
class PDFUserDetailView(PDFTemplateResponseMixin, DetailView):
model = Load
template_name = 'loads/load_pdf.html'
def load_list(request):
loads =
Load.objects.filter(company=request.company).order_by('date_created')
return render(request, 'loads/load_list.html', {'loads':loads})
I was able to get the query working based on the user, so my thought is that this query would be the same. This is not the case. I have a feeling that i'm referencing company wrong and maybe I somehow need to filter 2 more levels down all the way to the original UserCompany class, just not sure how to accomplish that.
The error that i'm getting is:
AttributeError: 'WSGIRequest' object has no attribute 'company'
request.company isn't a thing you can do. Instead of
Load.objects.filter(company=request.company).order_by('date_created')
You try something like this:
current_user = request.user
company = current_user.userprofileinfo.company
Load.objects.filter(company=company).order_by('date_created')
request just holds information about the current request which you can read more about here