I want to make an API to allow client to order online.
When the order is validated, I want to send an email to the client to confirm his order.
For that, I need the data that I just created (the order id, the delivery day and the delivery place).
This is my code : models.py :
class memberArea(AbstractBaseUser):
username = models.CharField(max_length=255)
email = models.EmailField(max_length=255, unique=True)
phone = models.TextField()
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
deliveryAddress = models.TextField()
postalCode = models.CharField(max_length=255)
forget = models.TextField(null=True, blank=True)
city = models.CharField(max_length=255)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
class order(models.Model):
user = models.ForeignKey(memberArea, on_delete=models.CASCADE)
comment = models.TextField(null=True, blank=True)
orderDay = models.DateTimeField(auto_now_add=True)
deliveryDay = models.DateField()
deliveryAddress = models.CharField(max_length=255)
state = models.CharField(max_length=255, null=True, blank=True, default="En attente")
price = models.TextField(null=True, blank=True)
response = models.TextField(null=True, blank=True)
class orderDetail(models.Model):
order = models.ForeignKey(order, on_delete=models.CASCADE)
product = models.ForeignKey(product, on_delete=models.CASCADE)
byProduct = models.ForeignKey(byProduct, on_delete=models.CASCADE)
quantity = models.CharField(max_length=255)
serializer.py :
class orderDetailSerializer(serializers.ModelSerializer):
class Meta:
model = orderDetail
fields = '__all__'
read_only_fields = ('order',)
class MakeOrderSerializer(serializers.ModelSerializer):
orderDetail = orderDetailSerializer(many=True)
class Meta:
model = order
fields = ['user', 'comment', 'deliveryAddress', 'deliveryDay', 'orderDetail']
def create(self, validated_data):
order_detail_data = validated_data.pop('orderDetail')
new_order = order.objects.create(**validated_data)
new_order.save()
for product in order_detail_data:
order_detail = orderDetail.objects.create(order=new_order, **product)
return new_order
views.py :
#Make an order
#api_view(['POST'])
def order(request, format=None):
if request.method == 'POST':
serializer = MakeOrderSerializer(data=request.data)
data = {}
if serializer.is_valid():
serializer.save()
data['response'] = "Your order went well"
delivery_date = serializer.data['deliveryDay']
delivery_place = serializer.data['deliveryAddress']
order_id = serializer.data['id']
message = "Thanks for your older.<br/>You will receive your order the <strong>{}</strong><br/>Delivery Place : <strong>{}/strong>.<br/>Order ID: <strong>{}</strong>.<br/>".format('delivery_day', 'delivery_address', 'order_id')
send_mail(
"Validation of your order !",
message,
"myaddress#gmail.com",
["useraddress#gmail.com"],
fail_silently=False,
)
return Response(data)
return Response(serializer.errors)
When I try to use my variables and run my code, this is what I get : Got AttributeError when attempting to get a value for field `orderDetail` on serializer `MakeOrderSerializer`. The serializer field might be named incorrectly and not match any attribute or key on the `order` instance. Original exception text was: 'order' object has no attribute 'orderDetail'.
Thanks by advance for helping me.
To access data from serializer you can use serializer.data['deliveryDate']. Similarly you can access serializer.data['orderDetail'] it will return a list, then you can iterate over it to access your other data.
Related
I want to get username from custom users model
My Custom Users model:
class Account(AbstractBaseUser, PermissionsMixin):
nickname = models.CharField(max_length=150, unique=True)
name = models.CharField(max_length=150)
last_name = models.CharField(max_length=150)
phone = models.CharField(max_length=50, unique=True)
date_of_birth = models.DateField(blank=True, null=True)
picture = models.ImageField(blank=True, null=True)
is_staff = models.BooleanField(default=True)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(default=timezone.now)
last_login = models.DateTimeField(null=True)
admin_of_company = models.ForeignKey('companies.company', on_delete=models.CASCADE, default=None, blank=True,
null=True)
objects = AccountManager()
USERNAME_FIELD = 'nickname'
REQUIRED_FIELDS = ['name', 'last_name', 'phone']
def get_full_name(self):
return self.name, self.last_name
def get_short_name(self):
return self.name.split()[0]
and products model:
class products(models.Model):
name = models.CharField(max_length=150)
about = models.TextField()
price = models.IntegerField()
picture = models.ImageField(default=None)
admin = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True)
in products.admin I want to set default logged in user
but I don't know how to get this data from custom users model
If you would like to get a current account in your view use this
current_user_id = self.request.user.id
current_account = Account.objects.get(pk=current_user_id)
current_account_nickname = current_account.nickname
Your model Account doesn't have "username" field.
You have to add it if you would like to use "username".
class Account(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=150, unique=True)
When I run api request I get a following error:
AttributeError: Got AttributeError when attempting to get a value for field email on serializer UserSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the tuple instance.
Original exception text was: 'tuple' object has no attribute 'email'.
New user gets inserted in database anyway, email field is filleld properly.
View:
class Register(APIView):
def post(self, request):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save()
if user:
return Response(serializer.data, status=status.HTTP_201_CREATED)
Serializer:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['email', 'username', 'name', 'password']
def create(self, validated_data):
user = User.objects.create_user(**validated_data),
return user
Model:
class User(AbstractBaseUser):
email = models.EmailField(max_length=254, unique=True)
username = models.CharField(max_length=30, unique=True)
name = models.CharField(max_length=60)
date_of_birth = models.DateField(blank=True, null=True)
bio = models.CharField(default='', max_length=10000)
photo = models.ImageField(max_length=255, null=True, blank=True)
email_verified_at = models.DateTimeField(null=True, blank=True)
email_token_time = models.DateTimeField(null=True, blank=True)
email_token = models.CharField(default='', max_length=64)
password_token_time = models.DateTimeField(null=True, blank=True)
password_token = models.CharField(default='', max_length=64)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
last_seen = models.DateTimeField(null=True, blank=True)
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = ['username', 'name']
objects = UserManager()
class Meta:
db_table = "User"
def __str__(self):
return self.username
I also have custom user manager, but that is probably irrelevant, and works as user does get inserted to database.
You have typo in this line:
user = User.objects.create_user(**validated_data),
It contains comma , in the last of line. So user become a tuple of user instance, not just user instance. It become (user,).
Should return user instance.
I am using a custom User model. And I have another Customer model. I want the user field will only show the staff user no other type of user in the field will show in the registration form. In my case, it is showing all types of users whether it is staff or customer or a service user.
Models.py
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=254, unique=True)
name = models.CharField(max_length=254, null=True)
email = models.EmailField(max_length=254, null=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_Customer = models.BooleanField(default=False)
is_Service_Provider = models.BooleanField(default=False)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'username'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
def get_absolute_url(self):
return "/users/%i/" % self.pk
def get_username(self):
return self.username
class Customer(models.Model):
user = models.OneToOneField('accounts.User', on_delete=models.SET_NULL, null=True)
email = models.EmailField(max_length=254, null=False)
date_Of_Birth = models.DateField(null=False)
country = models.ForeignKey('accounts.Country', null=True, on_delete=models.SET_NULL, related_name='Country')
state = models.ForeignKey('accounts.State', null=True, on_delete=models.SET_NULL, related_name='State')
city = models.ForeignKey('accounts.City', null=True, on_delete=models.SET_NULL, related_name='city')
address = models.CharField(max_length=254, null=False)
refernce_by_person_name = models.CharField(max_length=254, null=True)
refernce_by_person_contact_no = models.IntegerField(null=True)
phone_no = models.IntegerField(null=False)
alternate_no = models.IntegerField(null=False)
hobbies = models.CharField(max_length=254)
def __str__(self):
return self.user.username
views.py
def form(request):
forms = CustomerRegistrationForm()
if request.method == "POST":
forms = CustomerRegistrationForm(request.POST)
if forms.is_valid():
forms.save()
return redirect('/customer/show')
context = {
'forms' : forms,
}
return render(request,'customer/form.html', context)
forms.py
class CustomerRegistrationForm(forms.ModelForm):
class Meta:
model = Customer
fields = '__all__'
You can filter the staff users in the form like this.
class CustomerRegistrationForm(forms.ModelForm):
user = forms.ModelChoiceField(queryset=User.objects.filter(is_staff=True))
class Meta:
model = Customer
fields = ['user','email','date_of_birth',...]
I'm calling an API to update the my liked_products many to many model in Django but, when calling the prod ID to add the item to the list, I get the error:
AttributeError at /api/customer/like_product/
'ReturnDict' object has no attribute 'liked_products'
Here is my API:
#csrf_exempt
def updated_liked_products(request):
customer = get_user(request)
if not customer:
return JsonResponse({'invalid token'})
customer_details = CustomerDetailSerializer(CustomerDetails.objects.get(
customer=customer)).data
customer_details.liked_products.add(request.data['prodId'])
customer_details.save()
return JsonResponse({"success": 'updated'})
Customer Details Model:
age = models.IntegerField(default="21", blank=True)
address = models.CharField(
default='', max_length=254, null=True, blank=True)
nick_name = models.CharField(
default='', max_length=254, blank=True)
average_order = models.FloatField(default="0.0", blank=True)
completed_orders = models.IntegerField(default="0", blank=True)
customer = models.ForeignKey(
Customer, on_delete=models.CASCADE)
customer_type = MultiSelectField(
choices=CUSTYPE, default=CUSTYPE, max_length=100)
current_selfie = models.ImageField(
upload_to='sefies/', blank=True, default='')
email_confirmed = models.BooleanField(default=False)
last_signin = models.DateTimeField(default=timezone.now)
liked_products = models.ManyToManyField('Product')
needs_help_with = MultiSelectField(
choices=CATEGORIES, max_length=1000, default='')
phone = models.CharField(
I am using Postman to update the data like this so I can see the liked product field but, cannot access it.:
You're having this error because you're trying to access liked_products attribute on a serialized data that is an instance of ReturnDict and not CustomerDetails.
It seems like there is not much point in the serializer usage in this API so you should be able to achieve what you want with just this:
#csrf_exempt
def updated_liked_products(request):
customer = get_user(request)
if not customer:
return JsonResponse({'invalid token'})
customer_details = CustomerDetails.objects.get(customer=customer)
customer_details.liked_products.add(request.data['prodId'])
return JsonResponse({"success": 'updated'})
I have a Django 'add business' view which adds a new business with an inline 'business_contact' form.
The form works fine, but I'm wondering how to write up the unit test - specifically, the 'postdata' to send to self.client.post(settings.BUSINESS_ADD_URL, postdata)
I've inspected the fields in my browser and tried adding post data with corresponding names, but I still get a 'ManagementForm data is missing or has been tampered with' error when run.
Anyone know of any resources for figuring out how to post inline data?
Relevant models, views & forms below if it helps. Lotsa thanks.
MODEL:
class Contact(models.Model):
""" Contact details for the representatives of each business """
first_name = models.CharField(max_length=200)
surname = models.CharField(max_length=200)
business = models.ForeignKey('Business')
slug = models.SlugField(max_length=150, unique=True, help_text=settings.SLUG_HELPER_TEXT)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
phone = models.CharField(max_length=100, null=True, blank=True)
mobile_phone = models.CharField(max_length=100, null=True, blank=True)
email = models.EmailField(null=True)
deleted = models.BooleanField(default=False)
class Meta:
db_table='business_contact'
def __unicode__(self):
return '%s %s' % (self.first_name, self.surname)
#models.permalink
def get_absolute_url(self):
return('business_contact', (), {'contact_slug': self.slug })
class Business(models.Model):
""" The business clients who you are selling products/services to """
business = models.CharField(max_length=255, unique=True)
slug = models.SlugField(max_length=100, unique=True, help_text=settings.SLUG_HELPER_TEXT)
description = models.TextField(null=True, blank=True)
primary_contact = models.ForeignKey('Contact', null=True, blank=True, related_name='primary_contact')
business_type = models.ForeignKey('BusinessType')
deleted = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
address_1 = models.CharField(max_length=255, null=True, blank=True)
address_2 = models.CharField(max_length=255, null=True, blank=True)
suburb = models.CharField(max_length=255, null=True, blank=True)
city = models.CharField(max_length=255, null=True, blank=True)
state = models.CharField(max_length=255, null=True, blank=True)
country = models.CharField(max_length=255, null=True, blank=True)
phone = models.CharField(max_length=40, null=True, blank=True)
website = models.URLField(null=True, blank=True)
class Meta:
db_table = 'business'
def __unicode__(self):
return self.business
def get_absolute_url(self):
return '%s%s/' % (settings.BUSINESS_URL, self.slug)
VIEWS:
def business_add(request):
template_name = 'business/business_add.html'
if request.method == 'POST':
form = AddBusinessForm(request.POST)
if form.is_valid():
business = form.save(commit=False)
contact_formset = AddBusinessFormSet(request.POST, instance=business)
if contact_formset.is_valid():
business.save()
contact_formset.save()
contact = Contact.objects.get(id=business.id)
business.primary_contact = contact
business.save()
#return HttpResponse(help(contact))
#business.primary = contact.id
return HttpResponseRedirect(settings.BUSINESS_URL)
else:
contact_formset = AddBusinessFormSet(request.POST)
else:
form = AddBusinessForm()
contact_formset = AddBusinessFormSet(instance=Business())
return render_to_response(
template_name,
{
'form': form,
'contact_formset': contact_formset,
},
context_instance=RequestContext(request)
)
FORMS:
class AddBusinessForm(ModelForm):
class Meta:
model = Business
exclude = ['deleted','primary_contact',]
class ContactForm(ModelForm):
class Meta:
model = Contact
exclude = ['deleted',]
AddBusinessFormSet = inlineformset_factory(Business,
Contact,
can_delete=False,
extra=1,
form=AddBusinessForm,
)
The problem is you have not included the management form in your data. You need to include form-TOTAL_FORMS (total number of forms in the formset, default is 2), form-INITIAL_FORMS (the initial number of forms in the formset, default is 0) and form-MAX_NUM_FORMS (the maximum number of forms in the formset, default is '').
See the Formset documentation for more information on the management form.