How to DRY repeating block lists in Terraform - amazon-web-services

I have the following configuration and I would like to avoid the repetition of registrant_contact, admin_contact and tech_contact. How can I make this configuration shorter? I have multiple domains and the same block list repeats in the configuration file again and again:
locals {
contact = {
address_line_1 = "Berlin"
city = "Berlin"
contact_type = "PERSON"
country_code = "DE"
email = var.aws_billing_mails[0]
first_name = "Foo"
last_name = "Bar"
zip_code = "12345"
phone_number = "+49.123456789"
}
}
resource "aws_route53domains_registered_domain" "my_domain" {
domain_name = "mydomain.com"
auto_renew = true
transfer_lock = true
registrant_privacy = true
admin_privacy = true
tech_privacy = true
registrant_contact {
address_line_1 = local.contact.address_line_1
city = local.contact.city
contact_type = local.contact.contact_type
country_code = local.contact.country_code
email = local.contact.email
first_name = local.contact.first_name
last_name = local.contact.last_name
zip_code = local.contact.zip_code
phone_number = local.contact.phone_number
}
admin_contact {
address_line_1 = local.contact.address_line_1
city = local.contact.city
contact_type = local.contact.contact_type
country_code = local.contact.country_code
email = local.contact.email
first_name = local.contact.first_name
last_name = local.contact.last_name
zip_code = local.contact.zip_code
phone_number = local.contact.phone_number
}
tech_contact {
address_line_1 = local.contact.address_line_1
city = local.contact.city
contact_type = local.contact.contact_type
country_code = local.contact.country_code
email = local.contact.email
first_name = local.contact.first_name
last_name = local.contact.last_name
zip_code = local.contact.zip_code
phone_number = local.contact.phone_number
}
}
resource "aws_route53domains_registered_domain" "my_other_domain" {
domain_name = "myotherdomain.com"
auto_renew = true
transfer_lock = true
registrant_privacy = true
admin_privacy = true
tech_privacy = true
registrant_contact {
address_line_1 = local.contact.address_line_1
city = local.contact.city
contact_type = local.contact.contact_type
country_code = local.contact.country_code
email = local.contact.email
first_name = local.contact.first_name
last_name = local.contact.last_name
zip_code = local.contact.zip_code
phone_number = local.contact.phone_number
}
admin_contact {
address_line_1 = local.contact.address_line_1
city = local.contact.city
contact_type = local.contact.contact_type
country_code = local.contact.country_code
email = local.contact.email
first_name = local.contact.first_name
last_name = local.contact.last_name
zip_code = local.contact.zip_code
phone_number = local.contact.phone_number
}
tech_contact {
address_line_1 = local.contact.address_line_1
city = local.contact.city
contact_type = local.contact.contact_type
country_code = local.contact.country_code
email = local.contact.email
first_name = local.contact.first_name
last_name = local.contact.last_name
zip_code = local.contact.zip_code
phone_number = local.contact.phone_number
}
}

There is nothing you can do about the blocks, but you can reduce the number of resources. So instead of having two aws_route53domains_registered_domain, you can have only one, with the help of for_each. For example:
locals {
contact = {
"mydomain.com" = {
address_line_1 = "Berlin"
city = "Berlin"
contact_type = "PERSON"
country_code = "DE"
email = var.aws_billing_mails[0]
first_name = "Foo"
last_name = "Bar"
zip_code = "12345"
phone_number = "+49.123456789"
},
"myotherdomain.com" = {
address_line_1 = "Berlin"
city = "Berlin"
contact_type = "PERSON"
country_code = "DE"
email = var.aws_billing_mails[0]
first_name = "Foo"
last_name = "Bar"
zip_code = "12345"
phone_number = "+49.123456789"
}
}
then
resource "aws_route53domains_registered_domain" "domain" {
for_each = local.contact
domain_name = each.key
auto_renew = true
transfer_lock = true
registrant_privacy = true
admin_privacy = true
tech_privacy = true
registrant_contact {
address_line_1 = each.value.address_line_1
city = each.value.city
contact_type = each.value.contact_type
country_code = each.value.country_code
email = each.value.email
first_name = each.value.first_name
last_name = each.value.last_name
zip_code = each.value.zip_code
phone_number = each.value.phone_number
}
admin_contact {
address_line_1 = each.value.address_line_1
city = each.value.city
contact_type = each.value.contact_type
country_code = each.value.country_code
email = each.value.email
first_name = each.value.first_name
last_name = each.value.last_name
zip_code = each.value.zip_code
phone_number = each.value.phone_number
}
tech_contact {
address_line_1 = each.value.address_line_1
city = each.value.city
contact_type = each.value.contact_type
country_code = each.value.country_code
email = each.value.email
first_name = each.value.first_name
last_name = each.value.last_name
zip_code = each.value.zip_code
phone_number = each.value.phone_number
}
}
UPDATE
If you always use same contact, then:
locals {
domains = ["mydomain.com", "myotherdomain.com"]
contact = {
address_line_1 = "Berlin"
city = "Berlin"
contact_type = "PERSON"
country_code = "DE"
email = var.aws_billing_mails[0]
first_name = "Foo"
last_name = "Bar"
zip_code = "12345"
phone_number = "+49.123456789"
}
}
then
resource "aws_route53domains_registered_domain" "my_domain" {
for_each = toset(local.domains)
domain_name = each.key
auto_renew = true
transfer_lock = true
registrant_privacy = true
admin_privacy = true
tech_privacy = true
registrant_contact {
address_line_1 = local.contact.address_line_1
city = local.contact.city
contact_type = local.contact.contact_type
country_code = local.contact.country_code
email = local.contact.email
first_name = local.contact.first_name
last_name = local.contact.last_name
zip_code = local.contact.zip_code
phone_number = local.contact.phone_number
}
admin_contact {
address_line_1 = local.contact.address_line_1
city = local.contact.city
contact_type = local.contact.contact_type
country_code = local.contact.country_code
email = local.contact.email
first_name = local.contact.first_name
last_name = local.contact.last_name
zip_code = local.contact.zip_code
phone_number = local.contact.phone_number
}
tech_contact {
address_line_1 = local.contact.address_line_1
city = local.contact.city
contact_type = local.contact.contact_type
country_code = local.contact.country_code
email = local.contact.email
first_name = local.contact.first_name
last_name = local.contact.last_name
zip_code = local.contact.zip_code
phone_number = local.contact.phone_number
}
}

Related

How to make many to many query set

Here My Branch table and Store Table
How many branch record available in store table and count. I'm try it but can't get it.
class Branch(models.Model): # Branch Master
status_type = (
("a",'Active'),
("d",'Deactive'),
)
name = models.CharField(max_length=100, unique=True)
suffix = models.CharField(max_length=8, unique=True)
Remark = models.CharField(max_length=200, null=True, blank=True)
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
create_at = models.DateTimeField(auto_now_add=True)
update_at = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=1, choices = status_type, default = 'a')
def __str__(self):
return self.name
class Store(models.Model):
status_type = (
("y",'Yes'),
("n","No")
)
branch = models.ManyToManyField(Branch)
asset = models.ForeignKey(Asset,on_delete=models.CASCADE)
asset_code = models.CharField(max_length=100, null=True, blank=True, unique = True)
model = models.CharField(max_length=250)
serial_no = models.CharField(max_length=200)
vendor = models.ForeignKey(Vendor,on_delete=models.CASCADE)
invoice_no = models.CharField(max_length=50)
purchase_date = models.DateField()
store_status = models.CharField(max_length=1, choices = status_type, default = "y", blank = True)
store_date = models.DateTimeField(null = True, blank = True)
assige = models.CharField(max_length=1, choices = status_type, default = "n", blank = True)
assige_date = models.DateTimeField(null = True, blank = True)
scrap = models.CharField(max_length=1, choices = status_type, default = "n", blank = True)
scrap_date = models.DateTimeField(null = True, blank = True)
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
create_at = models.DateTimeField(auto_now_add=True)
update_at = models.DateTimeField(auto_now=True)
Query
get store object
store_obj = Store.objects.get( id= 5)
try to get count of branch record
tempcount = Store.objects.filter( branch = store_obj ).count()
I'm tired to get branch count.
To get the count of branch records associated with a store, you should query the Branch model instead. Since reverse m2m queries are supported, you can simply do:
branch_count = Branch.objects.filter(store=store_obj).count()

Django ORM query for filtering product price between two number is not working properly

class Product(models.Model):
product_name = models.CharField(max_length=255,unique=True)
slug = models.SlugField(max_length=255)
brand = models.CharField(max_length=255)
price = models.CharField(max_length=255)
product_image_1 = models.ImageField(upload_to = 'photos/product',blank = False)
product_image_2 = models.ImageField(upload_to = 'photos/product', blank = False)
product_image_3 = models.ImageField(upload_to = 'photos/product', blank = False)
product_image_4 = models.ImageField(upload_to = 'photos/product',blank = False)
product_description = models.TextField()
category_id = models.ForeignKey(Categories,on_delete=models.CASCADE)
subcategory_id = models.ForeignKey(SubCategories, on_delete=models.CASCADE)
stock = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
def __str__(self):
return self.product_name
def get_url(self):
return reverse('product_detail',args = [self.category_id.slug , self.subcategory_id.slug,
self.slug ])
'''view'''
val=request.POST.get('value')
val = re.findall("\d+", val) # code to get all inigers from string
min_price = int(val[0])
max_price = int(val[1])
print(min_price)
print(max_price)
***product = Product.objects.filter(category_id = categories,is_active =
True,price__gte = min_price, price__lte = max_price)***
when i give value greater than max_value product object returns null object
I want all objects between the two min_value and max_value

Create token with different model than user in django

I am trying to create an authentication token for my model called Person, but the Token table asks me for a user_id as a foreign key, is there any way I can create tokens with a different User model?
This is my Person model:
class Person(AbstractBaseUser):
first_name = models.CharField('Nombre', max_length = 100)
last_name = models.CharField('Apellido', max_length = 100)
username = models.CharField('Username', max_length = 50)
nickname = models.CharField('Nickname', max_length = 50, null = True)
gener = models.IntegerField('Genero')
phone = models.CharField('Teléfono', max_length = 13, null = True)
birtday = models.DateField('Cumpleaños', auto_now=False, auto_now_add=False, null = True)
address_id = models.IntegerField('Dirección', null = True)
address_birtday_id = models.IntegerField('Lugar de Nacimiento', null = True)
email = models.EmailField('Correo', max_length=254)
password = models.CharField('Password', max_length = 700)
photo = models.CharField('Foto', max_length=254, null = True)
about_me = models.CharField('Biografía', max_length = 1000, null = True)
active = models.IntegerField('Activo')
connected = models.IntegerField('Conectado')
person_type_id = models.IntegerField('Tipo', null = True)
created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True)
updated_at = models.DateTimeField(auto_now=True, null=True, blank=True)
USERNAME_FIELD = 'username'
def __str__(self):
return '{0},{1}'.format(self.last_name, self.first_name)
This is my view:
class LoginPersonAPI(APIView):
def post(self, request):
serializer = LoginPersonSerializer(data = request.data)
if serializer.is_valid():
person = Person.objects.filter(username=serializer.validated_data['username'])
token = Token.objects.get_or_create(key = person[0].id)
if token:
return Response(token[0])
return Response(person[0].id, status = status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status = status.HTTP_400_BAD_REQUEST)
This is my serializer:
class LoginPersonSerializer(serializers.Serializer):
username = serializers.CharField()
password = serializers.CharField()
def login(self, validate_data):
instance = Person
instance.username = validate_data.get("username")
instance.password = validate_data.get("password")
instance.find()
return instance
and this is the error
null value in column "user_id" violates not-null constraint
DETAIL: Failing row contains (3, 2020-06-27 19:39:53.283721+00, null).

How do I make this serializer display correctly?

Django is giving me this error. The solution I've tried does not seem to work. It is asking me to make this an instance of Medication...Am I not already doing that? I'm trying to have two serializers cat and medication under the one careLogSerializer. Is that even possible? How can I best solve this error?
builtins.ValueError
ValueError: Cannot assign "OrderedDict([('name', 'carelog3'), ('duration', 'short'), ('frequency', '4')])": "CareLog.medication" must be a "Medication" instance.
Here is my serializer....
class CareLogSerializer(serializers.HyperlinkedModelSerializer):
cat = CatSerializer()
medication = MedicationSerializer()
# cat = CatSerializer(read_only=True) this allows put BUT TURNS OFF POST
class Meta:
model = CareLog
fields = (
'cat',
'slug',
'foster_manager',
'weight_unit_measure',
'weight_before_food',
'food_unit_measure',
'amount_of_food_taken',
'food_type',
'weight_after_food',
'stimulated',
'medication',
'medication_dosage_given',
'medication_dosage_unit',
'notes',
'created',
'photo',
)
extra_kwargs = {
'foster_manager': {
'read_only': True,
'required': False,
'lookup_field': 'id',
},
'medication': {
'read_only': True,
'required': False,
'lookup_field': 'slug',
},
'cat': {
'read_only': True,
'required': False,
'lookup_field': 'slug',
},
}
#staticmethod
def create(validated_data):
cat_data = validated_data.pop('cat')
cat_obj = Cat.objects.get(**cat_data)
return CareLog.objects.create(cat=cat_obj, **validated_data)
#staticmethod
def update(instance, validated_data):
instance.weight_unit_measure = validated_data['weight_unit_measure']
instance.weight_before_food = validated_data['weight_before_food']
instance.food_unit_measure = validated_data['food_unit_measure']
instance.amount_of_food_taken = validated_data['amount_of_food_taken']
instance.food_type = validated_data['food_type']
instance.weight_after_food = validated_data['weight_after_food']
instance.stimulated = validated_data['stimulated']
instance.stimulation_type = validated_data['stimulation_type']
instance.notes = validated_data['notes']
instance.save()
Here is my model
class CareLog(models.Model):
WEIGHT_MEASURE_CHOICES = (
('OZ', '(oz) Ounces'),
('LB', '(lb) Pounds'),
('G', '(G) Grams')
)
OUNCES = 'OZ'
POUNDS = 'LB'
GRAMS = 'G'
VOLUME_MEASURE_CHOICES = (
('ML', '(ml) Milliliters'),
('CC', '(cc) Cubic Centimeters'),
('OZ', '(oz) Ounces'),
('G', '(G) Grams')
)
MILLILITERS = 'ML'
CUBIC_CENTIMETERS = 'CC'
FOOD_TYPE_CHOICES = (
('MN', 'Mom (Nursing)'),
('BO', 'Bottle'),
('BS', 'Bottle / Syringe'),
('SG', 'Syringe Gruel'),
('GG', 'Syringe Gruel / Gruel'),
('G', 'Gruel')
)
BOTTLE = 'BO'
BOTTLE_SYRINGE = 'BS'
SYRINGE_GRUEL = 'SG'
SYRINGE_GRUEL_GRUEL = 'GG'
GRUEL = 'G'
STIMULATION_CHOICES = (
('UR', 'Urine'),
('FE', 'Feces'),
('UF', 'Urine / Feces'),
)
URINE = 'UR'
FECES = 'FE'
URINE_FECES = 'UF'
cat = models.ForeignKey(Cat)
slug = AutoSlugField(max_length=255, unique=True, blank=True, null=True)
foster_manager = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
weight_unit_measure = models.CharField(max_length=2, choices=WEIGHT_MEASURE_CHOICES, default=GRAMS)
weight_before_food = models.IntegerField(blank=True, null=True)
food_unit_measure = models.CharField(max_length=2, choices=WEIGHT_MEASURE_CHOICES, default=GRAMS)
amount_of_food_taken = models.IntegerField(blank=True, null=True)
food_type = models.CharField(max_length=2, choices=FOOD_TYPE_CHOICES, blank=True, null=True)
weight_after_food = models.IntegerField(blank=True, null=True)
stimulated = models.BooleanField(default=False)
stimulation_type = models.CharField(max_length=2, choices=STIMULATION_CHOICES, blank=True, null=True)
medication = models.ForeignKey(Medication, blank=True, null=True)
medication_dosage_given = models.FloatField(blank=True, null=True)
medication_dosage_unit = models.CharField(max_length=2, choices=VOLUME_MEASURE_CHOICES, blank=True, null=True,
help_text="If left blank this will default to "
"the default unit for the medication.")
notes = models.TextField(blank=True, null=True)
created = models.DateTimeField(auto_now_add=True)
photo = models.FileField(upload_to="kitty_photos", blank=True, null=True)
def save(self, *args, **kwargs):
# Update Cat's weight if 'Weight After Food' is updated
if self.weight_after_food:
self.cat.weight = self.weight_after_food
self.cat.save()
# Get all previous cat feedings
feedings = CareLog.objects.filter(cat=self.cat).order_by('-id')
if feedings:
# if the list of cat feedings contains the current, get rid of current from the list
if feedings[0] == self:
feedings = feedings[1:]
# TODO You broke it you fix it:
# If the feeding is a weight loss log it as the first/second/third
if self.weight_after_food < feedings[0].weight_after_food:
if self.cat.first_weight_loss:
self.cat.second_weight_loss = True
elif self.cat.second_weight_loss:
self.cat.third_weight_loss = True
elif self.cat.third_weight_loss:
self.cat.many_weight_losses = True
elif not self.cat.first_weight_loss:
self.cat.first_weight_loss = True
# Save Cat Object
self.cat.save()
if self.medication and not self.medication_dosage_unit:
self.medication_dosage_unit = self.medication.dosage_unit
super(CareLog, self).save(*args, **kwargs)
def __str__(self):
return "{cat}: {timestamp}".format(cat=self.cat.name, timestamp=self.created)
In your create method you need to do for medication same operation as for cat. Create object first and assign it to CareLog:
#staticmethod
def create(validated_data):
cat_data = validated_data.pop('cat')
cat_obj = Cat.objects.get(**cat_data)
med_data = validated_data.pop('medication')
med_obj = Medication.objects.create(**med_data)
return CareLog.objects.create(cat=cat_obj, medication=med_obj, **validated_data)
Otherwise Django trying to set as foreignkey's value dict object and raise the error.

Django - Admin Action form with ChoiceField of a list of Verbose_names

I have a model:
class Inventory(models.Model):
title = models.CharField(max_length=100, db_index=True)
product_code = models.CharField(max_length=100, db_index=True)
slug = models.SlugField(max_length=100, db_index=True)
description = models.TextField()
cost_ea = models.DecimalField(max_digits=6, decimal_places=2)
cost_ws = models.DecimalField(max_digits=6, decimal_places=2)
quantity = models.IntegerField()
main_image = models.ImageField(upload_to = 'inventory/images/main/', null = True, blank = True)
thumb_image = models.ImageField(upload_to = 'inventory/images/thumbs/', null = True, blank = True)
product_category = models.ForeignKey('inventory.Product_Type')
card_category = models.ForeignKey('inventory.Card_Type')
last_modified = models.DateTimeField(auto_now = True, auto_now_add = True, null = True, blank = True, editable = True)
created = models.DateTimeField(auto_now_add = True, null = True, blank = True, editable = True, default = datetime.datetime.now())
in_stock = models.BooleanField(default = False)
I'd like create a form field something like this (it will be on an intermediate page of an admin action):
form.ChoiceField(choices=Inventory.get_all_verbose_names)
Is there a function that exists to get all verbose names from a model? and if not, how can I go about doing this?
You could try something like
forms.ChoiceField(choices=((f.name, f.verbose_name) for f in Inventory._meta.fields))