I create tests for api and models. The issue is to test if models are created.
User model is this one:
class User(AbstractUser):
CUSTOMER = 1
EXECUTER = 2
USER_TYPES = (
(CUSTOMER, 'Customer'),
(EXECUTER, 'Executer'),
)
user_type = models.IntegerField(choices=USER_TYPES, default=EXECUTER, verbose_name='Тип пользователя')
balance = models.DecimalField(decimal_places=2, max_digits=7, default=0, verbose_name='Баланс')
def __str__(self):
return self.username
Task models look like:
class Task(models.Model):
title = models.CharField(max_length=255, verbose_name='Заголовок')
description = models.CharField(max_length=255, verbose_name='Описание')
money = models.DecimalField(max_digits=7, decimal_places=2, default=0, verbose_name='Цена')
assignee = models.ForeignKey('users.User', related_name='assignee', null=True, verbose_name='Исполнитель')
created_by = models.ForeignKey('users.User', related_name='created_by', verbose_name='Кем был создан')
I want to test models creation, but test model doesn't want to be made. Problem is in assignee and created by fields.
This is my test:
def test_creating_models_instance(self):
User.objects.create(username="assignee", first_name="First_name_2", last_name="Surname_2",
user_type=2, balance="16155.00")
User.objects.create(username="created_by", first_name="First_name_1", last_name="Surname_1",
user_type=1, balance="16155.00")
Task.objects.create(title="Task_1", description="Description_1", money="155.00",
assignee="assignee", created_by="created_by")
And I have mistake like:
self.field.remote_field.model._meta.object_name,
ValueError: Cannot assign "'assignee'": "Task.assignee" must be a "User" instance.
You need use instance instead of string:
def test_creating_models_instance(self):
assignee = User.objects.create(
username="assignee", first_name="First_name_2",
last_name="Surname_2", user_type=2, balance="16155.00")
created_by = User.objects.create(
username="created_by", first_name="First_name_1",
last_name="Surname_1", user_type=1, balance="16155.00")
Task.objects.create(title="Task_1", description="Description_1", money="155.00",
assignee=assignee, created_by=created_by)
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Related
First, I know there are a lot of answers regarding this error, but I can't understand why this is erroring out in my case. I am learning Django and any help would be highly appreciated.
I have a Ticket model with ForeignKey reference to Category, Type & GHDUser as below
models.py
`
# from accounts/models.py
class GHDUser(AbstractBaseUser, PermissionsMixin):
emp_id = models.IntegerField(primary_key=True)
email = models.EmailField(_('email address'),unique=True)
username = models.CharField(max_length=150, unique=True)
# from ticket/models.py
class Category(models.Model):
name = models.CharField(max_length=100)
class Meta:
verbose_name = 'Category'
verbose_name_plural = 'Categories'
def __str__(self):
return self.name
class Type(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
class Meta:
verbose_name = 'Type'
verbose_name_plural = 'Types'
def __str__(self):
return self.name
class Ticket(models.Model):
status_options = (
('open', 'Open'),
('pending', 'Pending'),
('closed', 'Closed')
)
priority_options = (
('high','High'),
('medium','Medium'),
('low','Low')
)
ticket_no = models.CharField(max_length=10, blank=True)
title = models.CharField(max_length=100)
description = models.TextField(max_length=1000)
category = models.ForeignKey(Category, on_delete=models.PROTECT, default=1)
type = models.ForeignKey(Type, on_delete=models.PROTECT, default=1)
file = models.FileField(upload_to=user_directory_path, blank=True, default='files/Default_Avatar.png')
raised_by_user = models.ForeignKey(GHDUser, on_delete=models.CASCADE, related_name='raised_ticket')
`
Now, I am able to create an instance for Ticket model from Admin Panel, but when I try to do the same via shell / using data from front end, I am getting the below error.
django.db.utils.IntegrityError: FOREIGN KEY constraint failed
Can you please help me understand what I am doing wrong ?
Note: IF INFORMATION BELOW IS NOT CLEAR TO UNDERSTAND - PLEASE ASK ME, I WILL UPDATE AND POST INFORMATION YOU NEED | It is important for me
In Warehouse(models.Model) I have amount attribute and
in ChosenProduct(models.Model) - quantity
I'm trying to get amount in Warehouse through chosen_products instance in App_formSerializer to add the quantity of chosen_product
But I can not get the chosen_products objects from instance
--> below Out:
class WarehouseSerializer(serializers.ModelSerializer):
category_name = serializers.ReadOnlyField(
source='category_product.category_name')
posted_user = serializers.ReadOnlyField(
source='posted_user.username')
class Meta:
model = Warehouse
fields = ['id', 'category_product', 'category_name', 'condition',
'product_name', 'amount', 'barcode', 'f_price', 'created_at', 'updated_at', 'posted_user']
class ChosenProductSerializer(serializers.ModelSerializer):
product_info = WarehouseSerializer(source='product', read_only=True)
period_info = Product_periodSerializer(source='period', read_only=True)
class Meta:
model = ChosenProduct
exclude = ('app_form',)
class App_formSerializer(serializers.ModelSerializer):
chosen_products = ChosenProductSerializer(many=True)
def update(self, instance, validated_data):
instance.terminated = validated_data.get('terminated', instance.terminated)
if instance.terminated == True :
print('-----------TRUE--------------------')
print(instance.chosen_products)
print('-----------PRINT--------------------')
instance.save()
return instance
class Meta:
model = App_form
fields = '__all__'
Out
-----------TRUE--------------------
creditapi.ChosenProduct.None
-----------PRINT--------------------
QUESTION UPDATED
models.py
class Warehouse(models.Model):
category_product = models.ForeignKey(
Category_product, on_delete=models.CASCADE)
product_name = models.CharField(max_length=200, unique=True)
condition = models.BooleanField(default=False)
amount = models.IntegerField()
barcode = models.BigIntegerField()
f_price = models.CharField(max_length=255, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
posted_user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
def __str__(self):
return self.product_name
class App_form(models.Model):
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,12}$', message="Phone number must be entered in the format: '998981234567'. Up to 12 digits allowed.")
terminated = models.BooleanField(default=False)
name = models.CharField(max_length=150)
phone_number = models.CharField(validators=[phone_regex], max_length=13)
def __str__(self):
return self.surname
class ChosenProduct(models.Model):
product = models.ForeignKey(Warehouse, on_delete=models.CASCADE)
quantity = models.IntegerField()
app_form = models.ForeignKey(App_form, on_delete=models.CASCADE, related_name='chosen_products')
def __str__(self):
return self.product.product_name
If you write instance.chose_products you access the manager, not the QuerySet that contains the items. You can use .all() to obtain the QuerySet with all the objects:
print(instance.chosen_products.all())
If you access a ForeignKey in reverse, you have a manager, since zero, one, or more elements can refer to the instance.
You can for example aggregate over the chose_products, for example if you want to retrieve the number of related chose_products, you can use:
print(instance.chosen_products.count())
I would however advise not store (aggregated) data in the App_form, but aggregate data when you need it. Data duplication is an anti-pattern, and it turns out it is hard to keep data in sync.
models.py
i have create foreignkey in table paymentsDetails i have stripe payment method which is working when user login session is created and by using session value i get the primarykey of that user by using 'ORM' method and then assign this primary key of specific user into the paymentdetails models field named as user_account_id
but i am getting error that i cannot assign 1 to PaymentsDetail.User_account_id must be a instance of UserAccountModel
class UserAccountModel(models.Model):
ContactEmail = models.EmailField(max_length=30)
FirstName = models.CharField(max_length=30)
LastName = models.CharField(max_length=40)
Counrty = models.CharField(max_length=50)
Phone = models.IntegerField()
ChooseUserName = models.CharField(max_length=30)
password = models.CharField(max_length=32)
EnterCaptcha = models.CharField(max_length=4)
payments = models.BooleanField(max_length=6, default=False)
showsponsor = models.CharField(max_length=30, default=False)
RegisteredDate = models.DateTimeField(auto_now_add=True, blank=True)
ActivationOn = models.DateField(auto_now_add=False,blank=True)
expiry_date = models.DateField(auto_now_add=False,blank=True)
def __str__(self):
return self.FirstName + ":" + self.ChooseUserName
class PaymentsDetail(models.Model):
refrer_name = models.CharField(max_length=32,default="", editable=False)
sponser_name = models.CharField(max_length=32)
status = models.CharField(default='comped', max_length=32)
s_id = models.CharField(max_length=32)
registered = models.DateTimeField(auto_now_add=True)
activated_date = models.DateField(auto_now_add=False)
Due_Date = models.DateField(auto_now_add=False)
payment = models.CharField(default='$',max_length=32)
User_Account_id = models.ForeignKey(UserAccountModel, on_delete=models.CASCADE, default=True, editable=True)
addprogrameReference = models.ForeignKey(AddProgramModel, on_delete=models.CASCADE, default=True, editable=True)
class Meta:
ordering = ['User_Account_id', 'addprogrameReference']
def str(self):
return self.refrer_name + ":" + self.user_account
i am getting the error
cannot assign 1 to PaymentsDetail.User_account_id must be a instance
of UserAccountModel
views.py
print("user payment"+str(charge.amount))
pays = str(charge.amount)
user_id = random.randint(0, 999) # returns a random integer
user = User.objects.get(username=str(rerredby))
userKey = user.pk
print("this one is for user upper")
# saving record
payment_insertion = PaymentsDetail.objects.create(
User_Account_id=userKey,
refrer_name=rerredby,
sponser_name=rerredby,
s_id=str(user_id),
registered=datetime.now(),
activated_date=datetime.now(),
Due_Date=datetime.now(),
payment=str(pays + "$"),
)
payment_insertion.save()
Simply change this string:
payment_insertion = PaymentsDetail.objects.create(
User_Account_id=user,
...)
You are trying to assign int object where Django expects an instance.
Your view implementation is not right. The model class expects the field User_Account_id to be an instance of of UserAccountModel (since, your model definition User_Account_id = models.ForeignKey(UserAccountModel, on_delete=models.CASCADE, default=True, editable=True) told it to expect it regardless of the your field name ending with an id). therefore, retrieve the UserAccountModel instance from db first.
However, if you still want to pass the id to instead of an object change the following in your view.
User_Account_id_id=userKey
ForeingKey fields can be populated by id instead of the concerned model object. But you have to append _id at the end of the field name e.g.
#models.py
class Author(models.Model):
name = models.CharField(max_length=250)
class Book(models.Model):
name = models.CharField(max_length=250)
author = models.ForeignKeyField(Author, on_delete=models.CASCADE)
# views.py
def create_book(request):
name = request.POST.get('name', '')
author_id = request.POST.get('author_id', '')
Book.objects.create(name=name, author_id=author_id)
return HttpResponse(status=201)
Notice that there is no author_id field defined in the Book model. This field is implicitly defined by django ORM once you defined author field as a ForeignKey reference to Author model.
I am trying to create tables using python/django and postgres. I create classes for each database table in models.py. When I try to create the migrations it gives me this errors:
File "..\database\models.py", line 40, in <module>
class group(models.Model):
File "database\models.py", line 41, in group
user_id = models.ForeignKey(user) TypeError: __init__() missing 1 required positional argument: 'on_delete'
This is my code
class user(models.Model):
STATUS_CHOICES = (
('active','Active'),
('not active', 'Not active')
)
user_id= models.AutoField(primary_key=True)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField(max_length=70, null=True, blank=True, unique=True)
phone = models.CharField( max_length=17, blank=True)
gender = models.CharField(max_length=50)
region = models.CharField(max_length=50)
password = models.CharField(widget=models.PasswordInput)
active = models.CharField(max_length=50, choices=STATUS_CHOICES, default='not active')
register_date = models.DateField(default=date.today)
def _str_(self):
return self.user_id
class train(models.Model):
train_CHOICES = (
('intercity', 'Intercity'),
('sprinter', 'Sprinter')
)
train_id= models.AutoField(primary_key=True)
train_type = models.CharField(max_length=50, choices=train_CHOICES, default='intercity')
def _str_(self):
return self.train_id
class group(models.Model):
user_id = models.ForeignKey(user)
group_id = models.AutoField(primary_key=True)
trip_id = models.ForeignKey(trip)
created_date = models.DateField(default=date.today)
started_at = models.DateTimeField()
def _str_(self):
return self.group_id
I am really new to Python. I assume there are many mistakes. Could you please give a hint?
Since Django 2.0, on_delete is required argument for ForeignKey (in older versions it defaults to CASCADE), you should add it for all ForeignKey fields:
user_id = models.ForeignKey(user, on_delete=models.CASCADE)
trip_id = models.ForeignKey(trip, on_delete=models.CASCADE)
Note on_delete=models.CASCADE means that on deleting user or trip object Django deletes the objects containing the ForeignKey. You can find list of other options here.
I want to create a ModelForm which gonna show some specific field of ControlInstruction if device_type of Device is equals DC. Otherwise show all fields.
Suppose,
if device type == 'DC':
show these filed in form-> on_off_flag, speed_flag, direction_flag
else:
show all
How can I do that?
class Device(models.Model):
DEVICE_TYPES = (
('AC', 'AC MOTOR'),
('DC', 'DC MOTOR'),
)
user = models.ForeignKey(User, on_delete=models.CASCADE)
device_id = models.CharField(max_length=64, unique=True, blank=False)
device_name = models.CharField(max_length=100, blank=False)
device_model = models.CharField(max_length=10)
device_type = models.CharField(max_length=2, choices=DEVICE_TYPES, blank=False)
location = models.CharField(max_length=150)
def __str__(self):
return self.device_name
class ControlInstruction(models.Model):
DIRECTION_CHOICES = (
('FW', 'Forward'),
('BW', 'Backward'),
)
# OneToOneField is is similar to a ForeignKey with unique=True, but the “reverse”
# side of the relation will directly return a single object.
device = models.OneToOneField(Device, on_delete=models.CASCADE, primary_key=True)
on_off_flag = models.BooleanField(default=False)
voltage_flag = models.FloatField(max_length=20, default=0)
current_flag = models.FloatField(max_length=20, default=0)
speed_flag = models.IntegerField(default=0, validators=[MinValueValidator(0), MaxValueValidator(100)])
direction_flag = models.CharField(max_length=2, choices=DIRECTION_CHOICES, default='FW')
frequency_flag = models.IntegerField(default=0)
I would recommend creating two forms, one including only the fields for a DC device, and one form with all of the fields. Then in your view, choose which form to use based on the device_type.
class DeviceForm(forms.ModelForm):
class Meta:
model = Device
fields = "__all__"
def __init__(self,*args,**kwargs):
super().__init__(*args, **kwargs)
if self.instance.pk:
if self.instance.device_type != "DC":
del self.fields["on_off_flag"]
del self.fields["speed_flag"]
del self.fields["direction_flag"]
But I dont recommended since you will find that this approach is very limited