I got an issue I was wondering is there is a way to send a notification from Many to Many to each new user who are integrated to Reservation (notification has to be sent only to new users who belongs to friends). At the Reservation creation, friends == Null and then admin can add some user.
Does anyone has an idea about how I can manage to do it?
Assume user == reservation admin and friends are user who can only have access to the reservation.
class Reservation(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
friends = models.ManyToManyField(User,blank=True,related_name='friends_reservation')
def notifs_reservation(sender, instance, *args, **kwargs):
reservation = instance
sender = reservation.user
n_seller = reservation.friends
notify = Notification(reservation=reservation, sender=sender, user=n_seller, notification_type=7)
notify.save()
send_mail(
subject = "Lorem",
message = render_to_string('notifs_reservation.html', {
'sender': reservation.user,
'n_userb': n_seller,
'channel': reservation.slug,
}),
from_email="example#example.co",
recipient_list=[n_seller.email]
)
post_save.connect(notifs_reservation, sender=Reservation)
Related
So I have my models like this.
class Box(models.Model):
objects = models.Manager()
name = models.CharField(max_length=100)
owner = models.ForeignKey('users.User', on_delete=models.CASCADE)
REQUIRED_FIELDS = [name, owner, icon]
class User(AbstractBaseUser):
objects = BaseUserManager()
email = models.EmailField(unique=True)
username = models.CharField(max_length=32, validators=[MinLengthValidator(2)], unique=True)
avatar = models.ImageField(upload_to='avatars/', default='avatars/default.jpg')
REQUIRED_FIELDS = [username, email]
class Member(models.Model):
objects = models.Manager()
box = models.ForeignKey('uploads.Box', on_delete=models.CASCADE, editable=False)
user = models.ForeignKey('users.User', on_delete=models.CASCADE, editable=False)
roles = models.ManyToManyField('roles.Role', through='roles.MemberRole')
invite = models.ForeignKey('users.Invite', null=True, blank=True, on_delete=models.CASCADE)
REQUIRED_FIELDS = [box, user]
I have a websockets framework with routing like this.
websocket_urlpatterns = [
path('gateway/', GatewayEventsConsumer.as_asgi()),
]
class GatewayEventsConsumer(AsyncWebsocketConsumer):
"""
An ASGI consumer for gateway event sending. Any authenticated
user can connect to this consumer. Users receive personalized events
based on the permissions they have.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
async def connect(self):
user = self.scope['user']
if user.is_anonymous:
# close the connection if the
# user isn't authenticated yet
await self.close()
for member in user.member_set.all():
# put user into groups according to the boxes
# they are a part of. Additional groups would be
# added mid-way if the user joins or creates
# a box during the lifetime of this connection
await self.channel_layer.group_add(member.box.id, self.channel_name)
await self.channel_layer.group_add(self.scope['user'].id, self.channel_name)
await self.accept()
async def disconnect(self, close_code):
for member in self.scope['user'].member_set.all():
# remove user from groups according to the boxes they
# are a part of. Additional groups would be
# removed mid-way if the user leaves or gets kicked
# out of a box during the lifetime of this connection
await self.channel_layer.group_discard(member.box.id, self.channel_name)
await self.channel_layer.group_discard(self.scope['user'].id, self.channel_name)
async def fire_event(self, event: dict):
formatted = {
'data': event['data'],
'event': event['event'],
}
box = event.get('box', None)
channel = event.get('overwrite_channel', None)
listener_perms = event.get('listener_permissions', [])
if not listener_perms or not box:
# box would be none if the event was user-specific
# don't need to check permissions. Fan-out event
# directly before checking member-permissions
return await self.send(text_data=json.dumps(formatted))
member = self.scope['user'].member_set.get(box=box)
if listener_perms in member.get_permissions(channel):
# check for permissions directly without any extra context
# validation. Because data-binding is outbound permission
# checking is not complex, unlike rest-framework checking
await self.send(text_data=json.dumps(formatted))
this is how I send ws messages.
(using django signals)
#receiver(post_delete, sender=Upload)
def on_upload_delete(instance=None, **kwargs) -> None:
async_to_sync(channel_layer.group_send)(
instance.box.id,
{
'type': 'fire_event',
'event': 'UPLOAD_DELETE',
'listener_permissions': ['READ_UPLOADS'],
'overwrite_channel': instance.channel,
'box': instance.box,
'data': PartialUploadSerializer(instance).data
}
)
The api needs to send box-specific events, so I have different groups for boxes.
Users which connect to these groups will receive the events they need.
So, when the user connects to the "gateway", I add the user to all the boxes they are a part of, (plus a private group to send user-specific information)
On disconnect, I remove them from the same.
However, I am facing issues here.
An example,
when an user joins a box during the scope of the connection, they would not receive the events that are being sent for that particular box.
when an user leaves a box during the scope of the connection, they would still receive events from that particular box.
Any ways to fix these issues?
relevant github discussion is here.
You can do this by adding 2 handlers similar to fire-event.
The first one adds a user to a group
The second one deletes a user from a group.
Then using Django Signals, send a websocket message to those handlers whenever a user becomes a box member or leaves the box
I have this model called business I want the foreinkey field owner to get the logged in user name automatically without bringing the dropdown button of all users, I have tried some methods, but it doesn't work. How can I autofill the owner field with the logged in user
models.py
class User(AbstractUser):
phone_number = models.CharField(('phone number'), max_length=15,default='+234',
help_text=('Field to save the phone number of the user.'),unique=True)
fullname=models.CharField(max_length=50)
Affidavit=models.ImageField(upload_to='media/')
class Business(models.Model):
owner = models.ForeignKey(User,on_delete=models.CASCADE,default=1)
Phone_Number=models.IntegerField(default='086878432',unique=True)
Figi_ID=models.IntegerField(blank=True)
views.py
def details_business(request):
if request.user.is_authenticated:
business_form=Business()
if request.method=='POST':
business_form=Business_owner_form(request.POST,request.FILES)
if business_form.is_valid():
bform=business_form
bform.owner=request.user
bform.save()
def dashboard(request):
if request.user.is_authenticated:
context = RequestContext(request)
data = Business.objects.all()
current=request.user
print(current)
context={"obj":img}
return render(request,'dashboard.html',context)
You were supposed to call the forms save method.
if business_form.is_valid():
business = business_form.save()
business.owner = request.user
business.save()
I'm building a learning website that stores various data about the user's progress. Currently, I'm using sessions to do this. I want the following behaviour:
Unregistered users can return to the site at a later date and the site will remember their progress.
When a user creates an account, they will not lose any data about progress already collected.
When a registered user logs out, their progress should be hidden.
When a registered user logs back in, their progress should be restored.
Sessions work great for behaviors 1-3, but on step 4 the progress fails to be restored. If I understand how Django handles sessions correctly, all of the session data is destroyed when the user logs out. What would be the best way to save this data and restore it again when the user logs back in?
It seems like there's no best one way to do this, but the solution I came up with works well so I thought I would share it.
I created a separate table for storing key/value pairs permanently for registered users. Ideally, you might want to store the data as serialized JSON similar to how the django_sesssion table works, but simple character fields will also work:
class account_data(models.Model):
username = models.CharField(max_length=30)
key = models.CharField(max_length=30)
value = models.CharField(max_length=30, null=True, blank=True)
class Meta:
unique_together = ("username", "key")
Each time I want to save or retrieve a key value pair, I check if the user is logged in. If they aren't, I save the data to the session. If they are, I save the data to the account_data table. I built some functions to handle this:
from account_manager.models import account_data
def getSessionOrAccountData(request, key):
if request.user.is_authenticated():
username = request.user.username
try:
record = account_data.objects.get(username=username, key=key)
return record.value
except:
return None
else:
if key in request.session.keys():
return request.session[key]
else:
return None
def setSessionOrAccountData(request, key, value):
if request.user.is_authenticated():
username = request.user.username
try:
record = account_data.objects.get(username=username, key=key)
record.value = value
record.save()
except account_data.DoesNotExist:
record = account_data(username=username, key=key, value=str(value))
record.save()
else:
request.session[key] = value
def deleteSessionOrAccountData(request, key):
if request.user.is_authenticated():
username = request.user.username
account_data.objects.filter(username=username).filter(key=key).delete()
else:
del request.session[key]
Finally, when a user creates a new account, I want to copy any session data they might have over to the account_data table. The following code is run right after the new user account is created:
# save all existing session data to new user account
for key in request.session.keys():
record = account_data(username=request.POST['username'],
key=key,
value=str(request.session[key]))
record.save()
For this purpose, you can use the Django session, when the user is a guest user, you can save the data using the session, and when the user login, copy the data and delete the guest user.
def Add_To_Cart(request, pk):
if request.user.is_authenticated:
user = request.user
try:
""" Customer Model """
""" you can create user or guest user in Customer Model """
authenticate_user, created = Customer.objects.get_or_create(user=user)
customer = authenticate_user
""" here you can get guest user account """
guest_user = Customer.objects.get(user=None)
""" i have two models for my E-commerce website(OrderPost|Order) """
""" here you can copy and create OrderPost objects from guest_user """
guest_orderitems = OrderPost.objects.get(user=guest_user, ordered=False)
order_item, created = OrderPost.objects.get_or_create(
user=customer,
item= guest_orderitems.item,
qunatity= guest_orderitems.qunatity,
ordered=False
)
guest_user.delete()
except:
authenticate_user, created = Customer.objects.get_or_create(user=user)
customer = authenticate_user
else:
""" When a guest user visits your website,
the guest user will be created without username and only with session_key """
try:
session_key = request.COOKIES['sessionid']
except:
return '0'
customer, created = Customer.objects.get_or_create(session_key=session_key)
I've already defined a custom user account that utilizes several built in's from the auth User model and, using the user link, links these with some additional fields that I needed to register a user on the database.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
relevant from my models.py
# additional model to incorporate our custom fields to the auth user model
class Account(models.Model):
user = models.OneToOneField(User) #link (pointer) to the users other information in User model
birthdate = models.DateField(blank = True, ) # True makes this field optional
gender = models.CharField(max_length = 1, choices = GENDER_CHOICE, null = True, blank = True)
def __unicode__(self): # define a unicode for the user to access
return u'%s %s' % (self.user.first_name, self.user.last_name) # return first and last name in shell
# custom form to gather information from the user for a new account
class UserRegistration(UserCreationForm):
#class RegistrationForm(forms.ModelForm):
class Meta:
model = User
fields = ("first_name", "last_name", "email", "username", "password1", "password2",)
# ensures uniqueness of user email addresses when registering
def clean_email(self):
print "In custom creation"
email = self.cleaned_data.get(email = 'email')
username = self.cleaned_data.get(username = 'username')
# checks if email address already exists
if User.objects.filter(email__iexact = self.cleaned_data['email']):
print "Email exists"
# if email and User.objects.filter(email__iexact = email).exclude(username=username).exists():
raise forms.ValidationError(u'Email Address is currently used by another user.')
return email
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
relevant from views.py
def Main(request):
if request.user.is_authenticated():
latest_events = Event.objects.all().order_by('-created')[:10] # Returns latest 10 events
my_events = Event.objects.filter(creator=request.user)[:10] # Returns up to 10 events created by current User
my_calendars = Calendar.objects.filter(creator=request.user) # Returns all calendars created by the user
authForm = None
loginForm = None
headerType = "header.html"
else:
latest_events = None
my_events = None
my_calendars = None
headerType = "header_main.html"
authForm = UserRegistration(request.POST or None)
print "Creating account UserRegistration" # TESTING PRINT
print "User email = %s " %(User._meta.get_field('email'))
if request.method == 'POST':
if authForm.is_valid():
newUser = authForm.save(commit=False)
newUser.save()
newUser = authenticate(username=request.POST['username'], password=request.POST['password1'])
login(request, newUser)
return HttpResponseRedirect('/signup/')
....
....
more code on success redirection
....
....
~~~~~~~~~~~~~~~~~~~~~~~~~~~
(I hope I didn't post too much code, just wanted to be thorough)
As you can see there are a few commented out attempts I've made recently. I tried using thee built in RegistrationFormUniqueForm() by downloading 'registration' but I don't actually want to make a new registration form since I already have a working one.
I moved on to trying another suggestion, the code under the comment
# custom form to display additional sign up information
When I tried registering a new user with an already registered email it did not throw any error and allowed the registration. I also tried changing the users email and it allowed the change to an already taken email with no objection.
Can anyone suggest a method for making user registration maintain a unique lock on each individual attempting to register with an email address that may already be taken? As well as preventing them from changing their email to one that is taken by a current user?
Thanks in advance.
EDIT: I made changes to the Models registration form def clean_email() and the def in views to reflect what I currently have that still does not work.
The indentation of your clean_email methods is wrong for both forms. At the moment, they are methods of the Meta class, so will never be called. For example, the registration form should be:
class RegistrationForm(UserCreationForm):
#class RegistrationForm(forms.ModelForm):
class Meta:
model = User
fields = ("first_name", "last_name", "email", "username", "password1", "password2",)
def clean_email(self):
"""ensures uniqueness of user email addresses when registering"""
email = self.cleaned_data.get('email')
This might not be the real problem -- it's easy to get the indentation wrong when pasting code into stack overflow. If that's the case, I'll delete the answer.
I have the following model:
class MyUser(User):
# some fields...
contact = models.ManyToManyField("self", through='Contact', symmetrical=False, related_name="contact_set" )
class Contact(models.Model):
user1 = models.ForeignKey( MyUser, related_name="contact_set1")
user2 = models.ForeignKey( MyUser, related_name="contact_set2")
confirmed = models.BooleanField()
and this view to create a contact
def add_contact( request, username=None ):
if username:
try:
user = MyUser.objects.get(username=username)
except User.DoesNotExist:
user = None
if user:
contact = Contact( user1 = MyUser.objects.get(pk=request.user.id), user2=user, confirmed=False )
contact.save()
return render_to_response( "accounts/add_contact.html", {'user': user,} )
else:
return HttpResponseRedirect("/home")
def list_contacts( request, username=None ):
if username:
try:
user = MyUser.objects.get(username=username)
except User.DoesNotExist:
user = None
else:
user = MyUser.objects.get(pk=request.user.id)
if user:
contacts = user.contacts.all()
return render_to_response("accounts/list_contacts.html", {'contacts': contacts,} )
else:
return HttpResponseRedirect("/home")
Ok now... the code should be verbose enough, so I'll explain it briefly: Social networking, users add others to their contacts ("friends", "buddies", however you call it). If user A adds user B, B is also in contact with A...
The code works... but only one-way. If I'm logged in as user A and want to add user B to my contacts, B will show up on my contact list, but not the other way around. But I want also to show up on B's contact list - it should make no difference, who added whom. How may I manage that?
Docs. Docs says to pass "self"(as string).
Also, see this question.
Good luck. I hope, you will succeed in development.