Update db on successful payment django - python

I have a model named 'Exhibition', where i enable users to create a new exhibition/event after filling out a form they are asked to pay some amount and are redirected to a payment gateway (paypal as per django-paypal), after successful payment i want to update my 'Exhibition' table only for those who have paid, users are requested to login before creating an event and i am also saving the user with the form in my db.
This is my view for saving the form:
def new_event(request):
form = NewEventForm(request.POST or None)
if form.is_valid():
save_it = form.save(commit=False)
save_it.user = request.user
save_it.save()
return render_to_response('new_event.html',locals(), context_instance=RequestContext(request))
and my model:
class Exhibition(models.Model):
user = models.ForeignKey(User, blank=True, null = True)
Type = models.ForeignKey('home.Type')
Category = models.ForeignKey('home.Category')
Country = models.ForeignKey('home.Country')
City = models.ForeignKey('home.City')
Event_name = models.CharField(max_length = 250)
Video_url = models.URLField(blank = True)
Event_start_date = models.DateField(blank = False)
Event_end_date = models.DateField(blank = False)
Discription = RichTextField(blank = False)
Contact_person = models.CharField(max_length=50,blank = True )
Company = models.CharField(max_length = 100,blank = True)
Company_website = models.URLField(blank = True)
Email = models.EmailField(blank = True)
Event_website = models.URLField(blank = True)
Event_email = models.EmailField(blank = True)
Venue = models.CharField(max_length = 250, blank = False)
Address = models.CharField(max_length = 250, blank = False)
Paid = models.IntegerField(max_length=2, default='0')
def __unicode__(self):
return '%s' % self.Event_name
#permalink
def get_absolute_url(self):
return ('view_category', None, { 'slug': self.Event_name })
If i use django-paypal view, i would be able to process payment but i don't know how to get the correct 'Exhibition - id' to update the db, shall i store it in cookies and how to do it?

I would try adding a post_save signal handler to django-paypal's model PayPalStandardBase and then use the transaction record's fields to identify your exhibition record. You could use the primary key field of your model and tell paypal that it is your item number for the transaction, or just add any other unique field you want to use as common identifier.
Check out the model here:
https://github.com/spookylukey/django-paypal/blob/master/paypal/standard/models.py
The signal handler would look like:
#receiver(post_save, sender=PayPalStandardBase)
def mark_as_paid(sender, instance=None, created=False, **kwargs):
if created:
e = Exhibition.objects.get(pk=instance.item_number)
e.Paid = ...
e.save()
You can add it to a models.py of yours or a signals.py which you then import elsewhere.

I would suggest adding a custom field containing the user id , and recover it when paypal notify you back.
See custom below :
https://developer.paypal.com/webapps/developer/docs/classic/ipn/integration-guide/IPNandPDTVariables/

Related

How can I display the added Friends to their respective user friends list?

I am developing a feature same like Facebook. means a user can send a friend request and then that specific user will accept the friend request. so it means they both become friends with each other.
Now how can I display them in such a way that user A is a friend of User B and vice versa?
That's how I have developed it but can't display both of the users in the friend's list.
models.py:
class AddToNetwork(models.Model):
NETWORK_CHOICES = (
('ADD', 'Add'),
('ACCEPT', 'Accept'),
('DELETE', 'Delete'),
)
id = models.UUIDField( primary_key = True, default = uuid.uuid4,editable = False)
add_to = models.ForeignKey(User, on_delete=models.CASCADE, related_name="add_to", null=True, blank=True)
added_from = models.ForeignKey(User, on_delete=models.CASCADE, related_name="add_from", null=True, blank=True)
network_status = models.CharField(max_length=30, choices = NETWORK_CHOICES)
added_at = models.DateTimeField(auto_now_add = True)
deleted_at = models.DateTimeField(auto_now = True)
def __str__(self):
return str(self.add_to)
Sending a friend request using the following method/logic:
def addToNetwork(request, id):
try:
add_to = User.objects.get(id = id)
current_user = User.objects.get(id = request.user.id)
network = AddToNetwork.objects.create(add_to = add_to, added_from=current_user,network_status = 'ADD')
messages.success(request,f'Request Sent to {add_to.first_name} {add_to.last_name}')
return redirect('userProfileDetail', id)
except User.DoesNotExist:
add_to = None
return render(request,'network/network_userProfile.html')
Accepting a friend request using the following logic:
def acceptNetworkRequest(request, id):
try:
# if 'accept_friendRequest' in request.GET:
friend_request = AddToNetwork.objects.get(id = id)
print("\n Friend Request \n", friend_request)
friend_request.network_status = 'ACCEPT'
friend_request.save()
messages.success(request, f'You accepted {friend_request.added_from.first_name} as a friend!')
return redirect('friends', id)
except AddToNetwork.DoesNotExist:
return render(request,'network/friendRequestList.html')
Logic to display the friends in the respective profiles:
def friends(request, id):
user = User.objects.get(id = request.user.id)
if user:
approved_friends = AddToNetwork.objects.filter(Q(added_from_id = user),network_status = 'ACCEPT')
context = {
'friends': approved_friends,
# 'approved': friend_to,
# ' key' : value
}
return render(request, 'friend_list.html', context)
Now I want to use the model attribute add_to and added_from so that I can display the friends in their respective profiles. At the moment, either it displays a friend which uses the add_to attribute or added_from.
template for friends_list:
{% for friend in friends %}
<tr>
<!-- <td scope="row">{{forloop.counter}}</td> -->
<td>{{friend.add_to.first_name}} {{friend.add_to.last_name}}</td>
<br>
</tr>
</tr>
{% endfor %}
is there anyone who can guide me?
EDIT:
my user model:
class User(AbstractUser):
username = None
id = models.UUIDField( primary_key = True, default = uuid.uuid4,editable = False)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.CharField(max_length=50, unique=True)
created_at = models.DateTimeField(auto_now_add = True)
updated_at = models.DateTimeField(auto_now = True)
friends = models.ManyToManyField("self", blank=True)
The way to get the list of friends from your current model would be something like this:
User.objects.filter(
Q(add_from=user)& # get requests sent by the user
Q(add_from__network_status='ACCEPT')| # must be accepted
Q(add_to=user)& # and those sent to the user
Q(add_to__network_status='ACCEPT') # must be accepted
)
This should work fine but you might want another model that actually stores the friend lists, you may find it to be more concise and manageable. Something like storing friends as a m2m field on the user or having a FriendList model that stores the main user and their friends.
Edit - my code above is incorrect, the add_from field accesses the related AddToNetwork objects but then doesn't access the users related to those objects. It's necessary to add __add_to and __added_from respectively to get back to the user again.
get_user_model().objects.filter(
Q(add_from__add_to=user)& # get requests sent by the user
Q(add_from__network_status='ACCEPT')| # must be accepted
Q(add_to__added_from=user)& # and those sent to the user
Q(add_to__network_status='ACCEPT') # must be accepted
)

NOT NULL constraint failed: registratie_inkomen.pg_id

This are my models:
class PersoonGegevens(models.Model):
# Voornaam en achternaam
voornaam = models.CharField(max_length=265,)
achternaam = models.CharField(max_length=265)
#username
user = models.OneToOneField(User, on_delete=models.CASCADE)
class inkomen(models.Model):
pg = models.ForeignKey(PersoonGegevens, on_delete=models.CASCADE)
inkomenfield = models.CharField(max_length=100)
This is the form:
class inkomenForm(forms.ModelForm):
class Meta():
model = inkomen
fields = ('inkomenfield',)
This is my view:
def tijdelijk(request):
#User id
user = request.user.id
if request.method == 'POST':
incoming = inkomenForm(data=request.POST)
if incoming.is_valid():
incoming.save()
return HttpResponse("saved")
else:
x = incoming.errors
print (x)
return HttpResponseRedirect('/tijdelijk')
else:
incoming = inkomenForm()
return render(request, 'index/tijdelijkeindex.html', {'inkomen':incoming})
I have tried:
incoming.save(commit=False)
incoming.pg = user
incoming.save
also readed the documentation about Inline formsets of django. But i dont really get
So i get the following error:(NOT NULL constraint failed) and i know it comes because i need to assign the pg.id and i know i can do that by adding the field in the form.py and let the user choose the id. But what i actually want is that pg = the logged in user.
You need to assign the return value of form.save(commit=False) to a variable, the return value is the created (but not committed to the database) model object
obj = incoming.save(commit=False)
obj.pg = user
obj.save()

How to assign value of field of one model to field of another model?

Say, I have a view function that creates a Vacancy object on saving the form, and it has the field company that, if the form is valid, has to be assigned with value of field name, that is on the other model named EmployerProfile, how can I do that? I have company as a foreign key on my model.
My models
class EmployerProfile(models.Model):
name = models.CharField(max_length = 64)
description = models.TextField()
username = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete = models.CASCADE)
class Vacancy(models.Model):
name = models.CharField(max_length = 64)
competences = models.CharField(max_length = 32)
salary = models.DecimalField(decimal_places = 2, max_digits = 10)
description = models.TextField(null = True)
company = models.ForeignKey(EmployerProfile, on_delete = models.CASCADE)
featured = models.BooleanField(default = False)
My view
#login_required(login_url = 'login')
def vacancyAddView(request):
if request.method == 'POST':
form = VacancyAddForm(request.POST)
if form.is_valid():
form.save()
return redirect('profile')
else:
form = VacancyAddForm()
context = {
'form':form
}
return render(request, "addVacancy.html", context)
My form
class VacancyAddForm(forms.ModelForm):
class Meta:
model = Vacancy
fields = [
'name',
'competences',
'description',
'salary',
]
P.S. I have tried adding this piece of code to my view, rigth after form.is_valid():
obj = EmployerProfile.objects.get(username = request.user)
form.instance.company = obj.name
but it didn't work, it returned the ValueError with text "Vacancy.company" must be a "EmployerProfile" instance.
P.P.S. I also tried to override the save method in my model like this
def save(self, *args, **kwargs):
self.company = self.EmployerProfile.name
super(Vacancy, self).save(*args, **kwargs)
but it didn't work either.
You can't do what you want. Your Vacancy model defines company as a foreign key, but you're trying to set it as a string.
class Vacancy(models.Model):
company = models.ForeignKey(EmployerProfile, on_delete = models.CASCADE)
However, here's what your view should change to be to work with your models as you've defined them currently.
#login_required(login_url = 'login')
def vacancyAddView(request):
if request.method == 'POST':
form = VacancyAddForm(request.POST)
if form.is_valid():
# Set the company
form.instance.company = request.user.employerprofile
form.save()
return redirect('profile')
else:
form = VacancyAddForm()
context = {
'form':form
}
return render(request, "addVacancy.html", context)
The basic issue here is that you can't set a ForeignKey field to be a string. If you want the user to be able to set the Company from the form, you have a couple of choices. One is to take what you have now in the form and use it to filter, e.g. something like:
company = EmployerProfile.objects.filter(name__iexact=form.cleaned_data['company'])
form.instance.company = company
Another would be to change the form so that instead of a text input, company is a ModelChoiceField, or a regular ChoiceField populated with the company choices available to the user.
In either case the end goal will be to ensure that the company field contains a foreign key to an EmployerProfile object, rather than the string name of a company.

Django Saving A Model With Form + Current User Data

I'm writing my first app in django and i have encountered a problem. I'm trying to make a booking system. I'm trying to save the reservation model. It works just fine while the user is logged out. But once i click submit while logged in nothing really happens. The site simply reloads. Can anyone point out what I'm doing wrong?
That's my model code:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE)
name = models.CharField(max_length = 100)
surname = models.CharField(max_length = 100)
phone = models.CharField(max_length = 9)
class Reservation(models.Model):
reservationID = models.AutoField(primary_key = True)
name = models.CharField(max_length = 100)
surname = models.CharField(max_length = 100)
phone = models.CharField(max_length = 9)
email = models.EmailField()
bookIn = models.DateField('Book in date', default = timezone.now)
bookOut = models.DateField('Book out date', default = timezone.now)
roomType = models.ForeignKey(Room_type, on_delete = models.CASCADE)
My form:
class Booking(forms.ModelForm):
class Meta:
model = Reservation
fields = ('name', 'surname', 'phone', 'email', 'roomType', 'bookIn', 'bookOut',)
widgets = {
'bookIn': forms.DateInput(attrs={'class': 'datepicker'}),
'bookOut': forms.DateInput(attrs={'class': 'datepicker'})
}
And my view:
form = Booking()
if request.method == 'POST':
form = Booking(request.POST)
if form.is_valid():
if request.user.is_authenticated:
reservation = Reservation()
guest = Profile.objects.get(user=request.user)
reservation.name = guest.name
reservation.surname = guest.surname
reservation.phone = guest.phone
reservation.email = guest.user.email
reservation.bookIn = form.cleaned_data.get('bookIn')
reservation.bookOut = form.cleaned_data.get('bookOut')
reservation.roomType = form.cleaned_data.get('roomType')
reservation.save()
else:
reservation = form.save()
reservation.save()
n = reservation.pk
return redirect('bookSuccess', n)
return render(request, 'hotel/bookRoom.html', {'form' : form})
I am assuming your form is not validating for some reason, and you need to catch it to see what might be going wrong. So you can update your view like this:
form = Booking(request.POST or None)
if request.method == 'POST':
if form.is_valid():
if request.user.is_authenticated:
reservation = form.save(commit=False)
# optimized the code
guest = Profile.objects.get(user=request.user)
reservation.name = guest.name
reservation.surname = guest.surname
reservation.phone = guest.phone
reservation.email = request.user.email
reservation.save()
else:
reservation = form.save() # removed duplicate save
n = reservation.pk
return redirect('bookSuccess', n)
return render(request, 'hotel/bookRoom.html', {'form' : form})
Update
You don't need to put null true and blank true in the model fields. You can pass the user data from view to form. and if the user is authenticated then pop the fields which is not necessary for authenticated user. Like this:
class Booking(forms.ModelForm):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super(Booking, self).__init__(*args, **kwargs)
if user.is_authenticated:
self.fields.pop('name') # or make them required false like this: self.fields['name'].required = False
self.fields.pop('surname')
# other fields unnecessary for authenticated user
# rest of the code
And use this form in view like this:
form = Booking(request.POST or None, user=request.user)

UNIQUE constraint failed: auth_user.username

I'm trying to store the First name and last name straight from the Facebook API to a User Auth model (which is extended with FacebookProfile model, containing webpull, id and year_formed)
Models.py
class FacebookProfile(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE)
id = models.PositiveIntegerField(primary_key = True)
#name = models.CharField(max_length = 200, null = True)
year_formed = models.PositiveIntegerField(default = 0)
webpull= models.CharField(max_length =1000, null = True)
Views.py
if request.method == 'GET':
print 'im here'
return render(request, "logV2.html")
if request.method == "POST":
first_name = request.POST.get('first_name')
last_name = request.POST.get('last_name')
print first_name, last_name
facebook_user = FacebookUserForm(data=request.POST)
facebook_profile = FacebookProfileForm()
has_account = authenticate(first_name = first_name, last_name = last_name)
if has_account:
print 'this has account'
login(request, has_account)
return HttpResponseRedirect('/music/home/')
else:
id_ = request.POST.get('id')
birthday = request.POST.get('year_formed')
webpull = request.POST.get('webpull')
if birthday == "undefined":
print 'im emplty'
year_formed = random.randint(1993,1998)
else:
year_formed = re.findall(r"[0-9][0-9][0-9][0-9]$", birthday)[0]
print id_, year_formed, webpull
print facebook_user
user = facebook_user.save()
profile = facebook_profile.save(commit = False)
profile.user = user
profile.webpull = webpull
profile.id = id_
## steal birtday fucntion from log
# move to new database facebook (neeed to change all artists to facebookprofile)
profile.year_formed = year_formed
profile.save()
#authenticate user. then log him in.
#user = authenticate(username = profile.user.username)
now_has_account = authenticate(first_name = first_name, last_name = last_name)
login(request, now_has_account)
#profile.save()
return HttpResponseRedirect('/music/home/')
In the views the code brakes at user = facebook_user.save()
I tried clearing the whole database,
also
What I'm receiving from the html is a form with first_name,last_name,id,year_formed,webpull. The data gets to the backend fine.
Forms.py
class FacebookUserForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name')
class FacebookProfileForm(forms.ModelForm):
class Meta:
model = FacebookProfile
fields = ('id', 'year_formed', 'webpull',)
what im authenticating
Auth_Backend.py
class OnlynameandsurnameAuth(ModelBackend):
def authenticate(self, first_name = None, last_name = None):
try:
return User.objects.get(first_name = first_name, last_name = last_name)
except:
return None
then
auth.py
admin.site.register(FacebookProfile)
the backend authentification
settings.py
AUTHENTICATION_BACKENDS = (
# ... your other backends
#'music.auth_backend.PasswordlessAuthBackend',
'music.auth_backend.OnlynameandsurnameAuth',
)
any ideas how to save the first_name and last_name without having a UNIQUE error?
Thanks! :D
If you use the default authenticate function not providing a password should always (?) fail, which means that
has_account = authenticate(first_name = first_name, last_name = last_name)
always will be None.
But the main problem is that you do not set a username for the new User, only first_name and last_name. This will work once, but after one User with an empty username was created the next attempt will fail, as Users need an unique username.
So: Add a username!
Besides that, I think that
user = facebook_user.save()
does not assign the User to "user" but the Form.
You should use facebook_user.instance.

Categories

Resources