Repository: saleor/saleor
Pull request: Improve naming of attributes
close #2969 

Renamed `ProductAttribtue` to `Attribute`
Renamed `AttributeChoiceValue` to `AttributeValue`

Problem statement:
Improve naming of ProductAttribute and AttributeChoiceValue
I think it's quite confusing that we have `ProductAttribute` with a corresponding value named as `AttributeChoiceValue`

In my opinion, we should unify this to `Attribute` and `AttributeValue`. 
`ProductAttribute` is used for both products and variants.

Hints from issue discussion:

Commit message: Rename ProductAttribute to Attribute in docstrings and help texts

Patch to review:
diff --git a/saleor/core/utils/random_data.py b/saleor/core/utils/random_data.py
index a25fb7f60fd..a9c3136cff4 100644
--- a/saleor/core/utils/random_data.py
+++ b/saleor/core/utils/random_data.py
@@ -29,8 +29,8 @@
 from ...order.utils import update_order_status
 from ...page.models import Page
 from ...product.models import (
-    AttributeChoiceValue, Category, Collection, Product, ProductAttribute,
-    ProductImage, ProductType, ProductVariant)
+    Attribute, AttributeValue, Category, Collection, Product, ProductImage,
+    ProductType, ProductVariant)
 from ...product.thumbnails import create_product_thumbnails
 from ...product.utils.attributes import get_name_from_attributes
 from ...shipping.models import ShippingMethod, ShippingMethodType, ShippingZone
@@ -159,9 +159,9 @@ def create_product_types_by_schema(root_schema):
 
 def set_product_attributes(product, product_type):
     attr_dict = {}
-    for product_attribute in product_type.product_attributes.all():
-        value = random.choice(product_attribute.values.all())
-        attr_dict[str(product_attribute.pk)] = str(value.pk)
+    for attribute in product_type.product_attributes.all():
+        value = random.choice(attribute.values.all())
+        attr_dict[str(attribute.pk)] = str(value.pk)
     product.attributes = attr_dict
     product.save(update_fields=['attributes'])
 
@@ -172,8 +172,8 @@ def get_variant_combinations(product):
     # Size has available values: [S, M], Color has values [Red, Green]
     # All combinations will be generated (S, Red), (S, Green), (M, Red),
     # (M, Green)
-    # Output is list of dicts, where key is product attribute id and value is
-    # attribute value id. Casted to string.
+    # Output is list of dicts, where key is Attribute id and value is
+    # AttributeValue id. Casted to string.
     variant_attr_map = {
         attr: attr.values.all()
         for attr in product.product_type.variant_attributes.all()}
@@ -332,7 +332,7 @@ def create_attribute(**kwargs):
         'slug': slug,
         'name': slug.title()}
     defaults.update(kwargs)
-    attribute = ProductAttribute.objects.get_or_create(**defaults)[0]
+    attribute = Attribute.objects.get_or_create(**defaults)[0]
     return attribute
 
 
@@ -343,7 +343,7 @@ def create_attribute_value(attribute, **kwargs):
         'name': name}
     defaults.update(kwargs)
     defaults['slug'] = slugify(defaults['name'])
-    attribute_value = AttributeChoiceValue.objects.get_or_create(**defaults)[0]
+    attribute_value = AttributeValue.objects.get_or_create(**defaults)[0]
     return attribute_value
 
 
diff --git a/saleor/dashboard/product/filters.py b/saleor/dashboard/product/filters.py
index 00a9ffc5814..e9441a22de1 100644
--- a/saleor/dashboard/product/filters.py
+++ b/saleor/dashboard/product/filters.py
@@ -5,7 +5,7 @@
     RangeFilter)
 
 from ...core.filters import SortedFilterSet
-from ...product.models import Category, Product, ProductAttribute, ProductType
+from ...product.models import Attribute, Category, Product, ProductType
 from ..widgets import MoneyRangeWidget
 
 PRODUCT_SORT_BY_FIELDS = {
@@ -62,24 +62,23 @@ def get_summary_message(self):
             number=counter) % {'counter': counter}
 
 
-class ProductAttributeFilter(SortedFilterSet):
+class AttributeFilter(SortedFilterSet):
     name = CharFilter(
-        label=pgettext_lazy('Product attribute list filter label', 'Name'),
+        label=pgettext_lazy('Attribute list filter label', 'Name'),
         lookup_expr='icontains')
     sort_by = OrderingFilter(
-        label=pgettext_lazy('Product attribute list filter label', 'Sort by'),
+        label=pgettext_lazy('Attribute list filter label', 'Sort by'),
         fields=PRODUCT_TYPE_SORT_BY_FIELDS.keys(),
         field_labels=PRODUCT_TYPE_SORT_BY_FIELDS)
 
     class Meta:
-        model = ProductAttribute
+        model = Attribute
         fields = []
 
     def get_summary_message(self):
         counter = self.qs.count()
         return npgettext(
-            'Number of matching records in the dashboard '
-            'product attributes list',
+            'Number of matching records in the dashboard attributes list',
             'Found %(counter)d matching attribute',
             'Found %(counter)d matching attributes',
             number=counter) % {'counter': counter}
@@ -97,12 +96,12 @@ class ProductTypeFilter(SortedFilterSet):
         label=pgettext_lazy(
             'Product type list filter label', 'Product attributes'),
         field_name='product_attributes',
-        queryset=ProductAttribute.objects.all())
+        queryset=Attribute.objects.all())
     variant_attributes = ModelMultipleChoiceFilter(
         label=pgettext_lazy(
             'Product type list filter label', 'Variant attributes'),
         field_name='variant_attributes',
-        queryset=ProductAttribute.objects.all())
+        queryset=Attribute.objects.all())
 
     class Meta:
         model = ProductType
diff --git a/saleor/dashboard/product/forms.py b/saleor/dashboard/product/forms.py
index 9db40de1f4b..9d534317d25 100644
--- a/saleor/dashboard/product/forms.py
+++ b/saleor/dashboard/product/forms.py
@@ -13,10 +13,10 @@
 from . import ProductBulkAction
 from ...core import TaxRateType
 from ...core.utils.taxes import DEFAULT_TAX_RATE_NAME, include_taxes_in_prices
-from ...core.weight import WeightField, get_default_weight_unit
+from ...core.weight import WeightField
 from ...product.models import (
-    AttributeChoiceValue, Category, Collection, Product, ProductAttribute,
-    ProductImage, ProductType, ProductVariant, VariantImage)
+    Attribute, AttributeValue, Category, Collection, Product, ProductImage,
+    ProductType, ProductVariant, VariantImage)
 from ...product.thumbnails import create_product_thumbnails
 from ...product.utils.attributes import get_name_from_attributes
 from ..forms import ModelChoiceOrCreationField, OrderedModelMultipleChoiceField
@@ -160,7 +160,7 @@ def check_if_variants_changed(self, has_variants):
 class AttributesMixin(object):
     """Form mixin that dynamically adds attribute fields."""
 
-    available_attributes = ProductAttribute.objects.none()
+    available_attributes = Attribute.objects.none()
 
     # Name of a field in self.instance that hold attributes HStore
     model_attributes_field = None
@@ -195,8 +195,8 @@ def get_saved_attributes(self):
             if value:
                 # if the passed attribute value is a string,
                 # create the attribute value.
-                if not isinstance(value, AttributeChoiceValue):
-                    value = AttributeChoiceValue(
+                if not isinstance(value, AttributeValue):
+                    value = AttributeValue(
                         attribute_id=attr.pk, name=value, slug=slugify(value))
                     value.save()
                 attributes[smart_text(attr.pk)] = smart_text(value.pk)
@@ -419,9 +419,9 @@ def save(self):
         VariantImage.objects.bulk_create(images)
 
 
-class ProductAttributeForm(forms.ModelForm):
+class AttributeForm(forms.ModelForm):
     class Meta:
-        model = ProductAttribute
+        model = Attribute
         exclude = []
         labels = {
             'name': pgettext_lazy(
@@ -430,9 +430,9 @@ class Meta:
                 'Product internal name', 'Internal name')}
 
 
-class AttributeChoiceValueForm(forms.ModelForm):
+class AttributeValueForm(forms.ModelForm):
     class Meta:
-        model = AttributeChoiceValue
+        model = AttributeValue
         fields = ['attribute', 'name']
         widgets = {'attribute': forms.widgets.HiddenInput()}
         labels = {
@@ -444,12 +444,12 @@ def save(self, commit=True):
         return super().save(commit=commit)
 
 
-class ReorderAttributeChoiceValuesForm(forms.ModelForm):
+class ReorderAttributeValuesForm(forms.ModelForm):
     ordered_values = OrderedModelMultipleChoiceField(
-        queryset=AttributeChoiceValue.objects.none())
+        queryset=AttributeValue.objects.none())
 
     class Meta:
-        model = ProductAttribute
+        model = Attribute
         fields = ()
 
     def __init__(self, *args, **kwargs):
diff --git a/saleor/dashboard/product/urls.py b/saleor/dashboard/product/urls.py
index cb54bf45da8..334e235a8d6 100644
--- a/saleor/dashboard/product/urls.py
+++ b/saleor/dashboard/product/urls.py
@@ -58,24 +58,24 @@
         views.ajax_upload_image, name='product-images-upload'),
 
     url(r'attributes/$',
-        views.attribute_list, name='product-attributes'),
+        views.attribute_list, name='attributes'),
     url(r'attributes/(?P<pk>[0-9]+)/$',
-        views.attribute_details, name='product-attribute-details'),
+        views.attribute_details, name='attribute-details'),
     url(r'attributes/add/$',
-        views.attribute_create, name='product-attribute-add'),
+        views.attribute_create, name='attribute-add'),
     url(r'attributes/(?P<pk>[0-9]+)/update/$',
-        views.attribute_edit, name='product-attribute-update'),
+        views.attribute_edit, name='attribute-update'),
     url(r'attributes/(?P<pk>[0-9]+)/delete/$',
-        views.attribute_delete, name='product-attribute-delete'),
+        views.attribute_delete, name='attribute-delete'),
     url(r'attributes/(?P<attribute_pk>[0-9]+)/value/add/$',
-        views.attribute_choice_value_create,
-        name='product-attribute-value-add'),
+        views.attribute_value_create,
+        name='attribute-value-add'),
     url(r'attributes/(?P<attribute_pk>[0-9]+)/value/(?P<value_pk>[0-9]+)/update/$',  # noqa
-        views.attribute_choice_value_edit,
-        name='product-attribute-value-update'),
+        views.attribute_value_edit,
+        name='attribute-value-update'),
     url(r'attributes/(?P<attribute_pk>[0-9]+)/value/(?P<value_pk>[0-9]+)/delete/$',  # noqa
-        views.attribute_choice_value_delete,
-        name='product-attribute-value-delete'),
+        views.attribute_value_delete,
+        name='attribute-value-delete'),
     url(r'attributes/(?P<attribute_pk>[0-9]+)/values/reorder/$',
-        views.ajax_reorder_attribute_choice_values,
-        name='product-attribute-values-reorder')]
+        views.ajax_reorder_attribute_values,
+        name='attribute-values-reorder')]
diff --git a/saleor/dashboard/product/views.py b/saleor/dashboard/product/views.py
index 4f8f073934b..9daa3e44937 100644
--- a/saleor/dashboard/product/views.py
+++ b/saleor/dashboard/product/views.py
@@ -14,13 +14,13 @@
 from ...core.utils import get_paginator_items
 from ...discount.models import Sale
 from ...product.models import (
-    AttributeChoiceValue, Product, ProductAttribute, ProductImage, ProductType,
+    Attribute, AttributeValue, Product, ProductImage, ProductType,
     ProductVariant)
 from ...product.utils.availability import get_availability
 from ...product.utils.costs import (
     get_margin_for_variant, get_product_costs_data)
 from ..views import staff_member_required
-from .filters import ProductAttributeFilter, ProductFilter, ProductTypeFilter
+from .filters import AttributeFilter, ProductFilter, ProductTypeFilter
 
 
 @staff_member_required
@@ -532,9 +532,9 @@ def ajax_upload_image(request, product_pk):
 @staff_member_required
 @permission_required('product.manage_products')
 def attribute_list(request):
-    attributes = (ProductAttribute.objects.prefetch_related('values')
+    attributes = (Attribute.objects.prefetch_related('values')
                   .order_by('name'))
-    attribute_filter = ProductAttributeFilter(request.GET, queryset=attributes)
+    attribute_filter = AttributeFilter(request.GET, queryset=attributes)
     attributes = [
         (attribute.pk, attribute.name, attribute.values.all())
         for attribute in attribute_filter.qs]
@@ -544,131 +544,131 @@ def attribute_list(request):
         'attributes': attributes, 'filter_set': attribute_filter,
         'is_empty': not attribute_filter.queryset.exists()}
     return TemplateResponse(
-        request, 'dashboard/product/product_attribute/list.html', ctx)
+        request, 'dashboard/product/attribute/list.html', ctx)
 
 
 @staff_member_required
 @permission_required('product.manage_products')
 def attribute_details(request, pk):
-    attributes = ProductAttribute.objects.prefetch_related('values').all()
+    attributes = Attribute.objects.prefetch_related('values').all()
     attribute = get_object_or_404(attributes, pk=pk)
     values = attribute.values.all()
     ctx = {'attribute': attribute, 'values': values}
     return TemplateResponse(
-        request, 'dashboard/product/product_attribute/detail.html', ctx)
+        request, 'dashboard/product/attribute/detail.html', ctx)
 
 
 @staff_member_required
 @permission_required('product.manage_products')
 def attribute_create(request):
-    attribute = ProductAttribute()
-    form = forms.ProductAttributeForm(request.POST or None, instance=attribute)
+    attribute = Attribute()
+    form = forms.AttributeForm(request.POST or None, instance=attribute)
     if form.is_valid():
         attribute = form.save()
         msg = pgettext_lazy('Dashboard message', 'Added attribute')
         messages.success(request, msg)
-        return redirect('dashboard:product-attribute-details', pk=attribute.pk)
+        return redirect('dashboard:attribute-details', pk=attribute.pk)
     ctx = {'attribute': attribute, 'form': form}
     return TemplateResponse(
         request,
-        'dashboard/product/product_attribute/form.html',
+        'dashboard/product/attribute/form.html',
         ctx)
 
 
 @staff_member_required
 @permission_required('product.manage_products')
 def attribute_edit(request, pk):
-    attribute = get_object_or_404(ProductAttribute, pk=pk)
-    form = forms.ProductAttributeForm(request.POST or None, instance=attribute)
+    attribute = get_object_or_404(Attribute, pk=pk)
+    form = forms.AttributeForm(request.POST or None, instance=attribute)
     if form.is_valid():
         attribute = form.save()
         msg = pgettext_lazy('Dashboard message', 'Updated attribute')
         messages.success(request, msg)
-        return redirect('dashboard:product-attribute-details', pk=attribute.pk)
+        return redirect('dashboard:attribute-details', pk=attribute.pk)
     ctx = {'attribute': attribute, 'form': form}
     return TemplateResponse(
         request,
-        'dashboard/product/product_attribute/form.html',
+        'dashboard/product/attribute/form.html',
         ctx)
 
 
 @staff_member_required
 @permission_required('product.manage_products')
 def attribute_delete(request, pk):
-    attribute = get_object_or_404(ProductAttribute, pk=pk)
+    attribute = get_object_or_404(Attribute, pk=pk)
     if request.method == 'POST':
         attribute.delete()
         msg = pgettext_lazy(
             'Dashboard message', 'Removed attribute %s') % (attribute.name,)
         messages.success(request, msg)
-        return redirect('dashboard:product-attributes')
+        return redirect('dashboard:attributes')
     return TemplateResponse(
         request,
-        'dashboard/product/product_attribute/modal/'
+        'dashboard/product/attribute/modal/'
         'attribute_confirm_delete.html',
         {'attribute': attribute})
 
 
 @staff_member_required
 @permission_required('product.manage_products')
-def attribute_choice_value_create(request, attribute_pk):
-    attribute = get_object_or_404(ProductAttribute, pk=attribute_pk)
-    value = AttributeChoiceValue(attribute_id=attribute_pk)
-    form = forms.AttributeChoiceValueForm(request.POST or None, instance=value)
+def attribute_value_create(request, attribute_pk):
+    attribute = get_object_or_404(Attribute, pk=attribute_pk)
+    value = AttributeValue(attribute_id=attribute_pk)
+    form = forms.AttributeValueForm(request.POST or None, instance=value)
     if form.is_valid():
         form.save()
         msg = pgettext_lazy(
             'Dashboard message', 'Added attribute\'s value')
         messages.success(request, msg)
-        return redirect('dashboard:product-attribute-details', pk=attribute_pk)
+        return redirect('dashboard:attribute-details', pk=attribute_pk)
     ctx = {'attribute': attribute, 'value': value, 'form': form}
     return TemplateResponse(
         request,
-        'dashboard/product/product_attribute/values/form.html',
+        'dashboard/product/attribute/values/form.html',
         ctx)
 
 
 @staff_member_required
 @permission_required('product.manage_products')
-def attribute_choice_value_edit(request, attribute_pk, value_pk):
-    attribute = get_object_or_404(ProductAttribute, pk=attribute_pk)
-    value = get_object_or_404(AttributeChoiceValue, pk=value_pk)
-    form = forms.AttributeChoiceValueForm(request.POST or None, instance=value)
+def attribute_value_edit(request, attribute_pk, value_pk):
+    attribute = get_object_or_404(Attribute, pk=attribute_pk)
+    value = get_object_or_404(AttributeValue, pk=value_pk)
+    form = forms.AttributeValueForm(request.POST or None, instance=value)
     if form.is_valid():
         form.save()
         msg = pgettext_lazy(
             'Dashboard message', 'Updated attribute\'s value')
         messages.success(request, msg)
-        return redirect('dashboard:product-attribute-details', pk=attribute_pk)
+        return redirect('dashboard:attribute-details', pk=attribute_pk)
     ctx = {'attribute': attribute, 'value': value, 'form': form}
     return TemplateResponse(
         request,
-        'dashboard/product/product_attribute/values/form.html',
+        'dashboard/product/attribute/values/form.html',
         ctx)
 
 
 @staff_member_required
 @permission_required('product.manage_products')
-def attribute_choice_value_delete(request, attribute_pk, value_pk):
-    value = get_object_or_404(AttributeChoiceValue, pk=value_pk)
+def attribute_value_delete(request, attribute_pk, value_pk):
+    value = get_object_or_404(AttributeValue, pk=value_pk)
     if request.method == 'POST':
         value.delete()
         msg = pgettext_lazy(
             'Dashboard message',
             'Removed attribute\'s value %s') % (value.name,)
         messages.success(request, msg)
-        return redirect('dashboard:product-attribute-details', pk=attribute_pk)
+        return redirect('dashboard:attribute-details', pk=attribute_pk)
     return TemplateResponse(
         request,
-        'dashboard/product/product_attribute/values/modal/confirm_delete.html',
+        'dashboard/product/attribute/values/modal/confirm_delete.html',
         {'value': value, 'attribute_pk': attribute_pk})
 
 
 @staff_member_required
 @permission_required('product.manage_products')
-def ajax_reorder_attribute_choice_values(request, attribute_pk):
-    attribute = get_object_or_404(ProductAttribute, pk=attribute_pk)
-    form = forms.ReorderAttributeChoiceValuesForm(
+def ajax_reorder_attribute_values(request, attribute_pk):
+    attribute = get_object_or_404(Attribute, pk=attribute_pk)
+    form = forms.ReorderAttributeValuesForm(
         request.POST, instance=attribute)
     status = 200
     ctx = {}
diff --git a/saleor/data_feeds/google_merchant.py b/saleor/data_feeds/google_merchant.py
index 9b809a1e858..bde6a0c8e1d 100644
--- a/saleor/data_feeds/google_merchant.py
+++ b/saleor/data_feeds/google_merchant.py
@@ -10,7 +10,7 @@
 
 from ..discount.models import Sale
 from ..product.models import (
-    AttributeChoiceValue, Category, ProductAttribute, ProductVariant)
+    Attribute, AttributeValue, Category, ProductVariant)
 
 CATEGORY_SEPARATOR = ' > '
 
@@ -198,9 +198,9 @@ def write_feed(file_obj):
     categories = Category.objects.all()
     discounts = Sale.objects.active(date.today()).prefetch_related(
         'products', 'categories')
-    attributes_dict = {a.slug: a.pk for a in ProductAttribute.objects.all()}
+    attributes_dict = {a.slug: a.pk for a in Attribute.objects.all()}
     attribute_values_dict = {smart_text(a.pk): smart_text(a) for a
-                             in AttributeChoiceValue.objects.all()}
+                             in AttributeValue.objects.all()}
     category_paths = {}
     current_site = Site.objects.get_current()
     for item in get_feed_items():
diff --git a/saleor/graphql/api.py b/saleor/graphql/api.py
index 16a864dbfe6..149538018b5 100644
--- a/saleor/graphql/api.py
+++ b/saleor/graphql/api.py
@@ -40,9 +40,9 @@
 from .page.mutations import PageCreate, PageDelete, PageUpdate
 from .product.filters import ProductFilterSet
 from .product.mutations.attributes import (
-    AttributeChoiceValueCreate, AttributeChoiceValueDelete,
-    AttributeChoiceValueUpdate, ProductAttributeCreate, ProductAttributeDelete,
-    ProductAttributeUpdate)
+    AttributeValueCreate, AttributeValueDelete,
+    AttributeValueUpdate, AttributeCreate, AttributeDelete,
+    AttributeUpdate)
 from .product.mutations.products import (
     CategoryCreate, CategoryDelete, CategoryUpdate,
     CollectionAddProducts, CollectionCreate, CollectionDelete,
@@ -56,7 +56,7 @@
     resolve_attributes, resolve_categories, resolve_collections,
     resolve_products, resolve_product_types, resolve_product_variants)
 from .product.types import (
-    Category, Collection, Product, ProductAttribute, ProductType,
+    Category, Collection, Product, Attribute, ProductType,
     ProductVariant)
 from .shipping.resolvers import resolve_shipping_zones
 from .shipping.types import ShippingZone
@@ -74,10 +74,10 @@ class Query(graphene.ObjectType):
         AddressValidationData,
         input=graphene.Argument(AddressValidationInput, required=True))
     attributes = DjangoFilterConnectionField(
-        ProductAttribute,
+        Attribute,
         query=graphene.String(description=DESCRIPTIONS['attributes']),
         in_category=graphene.Argument(graphene.ID),
-        description='List of the shop\'s product attributes.')
+        description='List of the shop\'s attributes.')
     categories = DjangoFilterConnectionField(
         Category, query=graphene.String(
             description=DESCRIPTIONS['category']),
@@ -278,9 +278,9 @@ class Mutations(graphene.ObjectType):
     set_password = SetPassword.Field()
     password_reset = PasswordReset.Field()
 
-    attribute_choice_value_create = AttributeChoiceValueCreate.Field()
-    attribute_choice_value_delete = AttributeChoiceValueDelete.Field()
-    attribute_choice_value_update = AttributeChoiceValueUpdate.Field()
+    attribute_value_create = AttributeValueCreate.Field()
+    attribute_value_delete = AttributeValueDelete.Field()
+    attribute_value_update = AttributeValueUpdate.Field()
 
     category_create = CategoryCreate.Field()
     category_delete = CategoryDelete.Field()
@@ -336,9 +336,9 @@ class Mutations(graphene.ObjectType):
     page_delete = PageDelete.Field()
     page_update = PageUpdate.Field()
 
-    product_attribute_create = ProductAttributeCreate.Field()
-    product_attribute_delete = ProductAttributeDelete.Field()
-    product_attribute_update = ProductAttributeUpdate.Field()
+    attribute_create = AttributeCreate.Field()
+    attribute_delete = AttributeDelete.Field()
+    attribute_update = AttributeUpdate.Field()
 
     product_create = ProductCreate.Field()
     product_delete = ProductDelete.Field()
diff --git a/saleor/graphql/product/filters.py b/saleor/graphql/product/filters.py
index 74267ad7b70..36733a6232f 100644
--- a/saleor/graphql/product/filters.py
+++ b/saleor/graphql/product/filters.py
@@ -8,11 +8,11 @@
 from graphene_django.filter.filterset import Filter, FilterSet
 
 from ...product.filters import SORT_BY_FIELDS
-from ...product.models import Product, ProductAttribute
+from ...product.models import Attribute, Product
 from .fields import AttributeField
 
 
-class ProductAttributeFilter(Filter):
+class AttributeFilter(Filter):
     field_class = AttributeField
 
     def filter(self, qs, value):
@@ -22,7 +22,7 @@ def filter(self, qs, value):
         if not value:
             return qs.distinct() if self.distinct else qs
 
-        attributes = ProductAttribute.objects.prefetch_related('values')
+        attributes = Attribute.objects.prefetch_related('values')
         attributes_map = {
             attribute.slug: attribute.pk for attribute in attributes}
         values_map = {
@@ -67,7 +67,7 @@ class Meta:
     @classmethod
     def filter_for_field(cls, f, field_name, lookup_expr='exact'):
         if field_name == 'attributes':
-            return ProductAttributeFilter(
+            return AttributeFilter(
                 field_name=field_name, lookup_expr=lookup_expr, distinct=True)
         # this class method is called during class construction so we can't
         # reference ProductFilterSet here yet
diff --git a/saleor/graphql/product/mutations/attributes.py b/saleor/graphql/product/mutations/attributes.py
index 09217718e42..18e8bb174f6 100644
--- a/saleor/graphql/product/mutations/attributes.py
+++ b/saleor/graphql/product/mutations/attributes.py
@@ -4,14 +4,14 @@
 from ...core.mutations import ModelDeleteMutation, ModelMutation
 
 
-class ProductAttributesInput(graphene.InputObjectType):
+class AttributesInput(graphene.InputObjectType):
     slug = graphene.String(
         required=True, description='Internal name.')
     name = graphene.String(
         required=True, description='Name displayed in the interface.')
 
 
-class AttributeChoiceValueInput(graphene.InputObjectType):
+class AttributeValueCreateInput(graphene.InputObjectType):
     attribute = graphene.ID(
         required=False,
         description='Attribute to which value will be assigned.',
@@ -24,85 +24,85 @@ class AttributeChoiceValueInput(graphene.InputObjectType):
         required=True, description='Real value eg. HEX color.')
 
 
-class AttributeChoiceValueUpdateInput(graphene.InputObjectType):
+class AttributeValueUpdateInput(graphene.InputObjectType):
     slug = graphene.String(
         required=True, description='Internal name.')
     name = graphene.String(
         required=True, description='Name displayed in the interface.')
 
 
-class ProductAttributeCreate(ModelMutation):
+class AttributeCreate(ModelMutation):
     class Arguments:
-        input = ProductAttributesInput(
+        input = AttributesInput(
             required=True,
-            description='Fields required to create a product attribute.')
+            description='Fields required to create an attribute.')
 
     class Meta:
-        description = 'Creates a product attribute.'
-        model = models.ProductAttribute
+        description = 'Creates an attribute.'
+        model = models.Attribute
 
     @classmethod
     def user_is_allowed(cls, user, input):
         return user.has_perm('product.manage_products')
 
 
-class ProductAttributeUpdate(ProductAttributeCreate):
+class AttributeUpdate(AttributeCreate):
     class Arguments:
         id = graphene.ID(
-            required=True, description='ID of a product attribute to update.')
-        input = ProductAttributesInput(
+            required=True, description='ID of an attribute to update.')
+        input = AttributesInput(
             required=True,
-            description='Fields required to update a product attribute.')
+            description='Fields required to update an attribute.')
 
     class Meta:
-        description = 'Updates a product attribute.'
-        model = models.ProductAttribute
+        description = 'Updates anattribute.'
+        model = models.Attribute
 
 
-class ProductAttributeDelete(ModelDeleteMutation):
+class AttributeDelete(ModelDeleteMutation):
     class Arguments:
         id = graphene.ID(
-            required=True, description='ID of a product attribute to delete.')
+            required=True, description='ID of an attribute to delete.')
 
     class Meta:
-        description = 'Deletes a product attribute.'
-        model = models.ProductAttribute
+        description = 'Deletes an attribute.'
+        model = models.Attribute
 
     @classmethod
     def user_is_allowed(cls, user, input):
         return user.has_perm('product.manage_products')
 
 
-class AttributeChoiceValueCreate(ModelMutation):
+class AttributeValueCreate(ModelMutation):
     class Arguments:
-        input = AttributeChoiceValueInput(
+        input = AttributeValueCreateInput(
             required=True,
             description='Fields required to create an attribute choice value.')
 
     class Meta:
         description = 'Creates an attribute choice value.'
-        model = models.AttributeChoiceValue
+        model = models.AttributeValue
 
     @classmethod
     def user_is_allowed(cls, user, input):
         return user.has_perm('product.manage_products')
 
 
-class AttributeChoiceValueUpdate(AttributeChoiceValueCreate):
+class AttributeValueUpdate(AttributeValueCreate):
     class Arguments:
         id = graphene.ID(
             required=True,
             description='ID of an attribute choice value to update.')
-        input = AttributeChoiceValueUpdateInput(
+        input = AttributeValueUpdateInput(
             required=True,
             description='Fields required to update an attribute choice value.')
 
     class Meta:
         description = 'Updates an attribute choice value.'
-        model = models.AttributeChoiceValue
+        model = models.AttributeValue
 
 
-class AttributeChoiceValueDelete(ModelDeleteMutation):
+class AttributeValueDelete(ModelDeleteMutation):
     class Arguments:
         id = graphene.ID(
             required=True,
@@ -110,7 +110,7 @@ class Arguments:
 
     class Meta:
         description = 'Deletes an attribute choice value.'
-        model = models.AttributeChoiceValue
+        model = models.AttributeValue
 
     @classmethod
     def user_is_allowed(cls, user, input):
diff --git a/saleor/graphql/product/mutations/products.py b/saleor/graphql/product/mutations/products.py
index 49f034d30b2..dbf22c04c24 100644
--- a/saleor/graphql/product/mutations/products.py
+++ b/saleor/graphql/product/mutations/products.py
@@ -199,7 +199,7 @@ class AttributeValueInput(InputObjectType):
 class ProductInput(graphene.InputObjectType):
     attributes = graphene.List(
         AttributeValueInput,
-        description='List of product attributes.')
+        description='List of attributes.')
     available_on = graphene.types.datetime.Date(
         description='Publication date. ISO 8601 standard.')
     category = graphene.ID(
diff --git a/saleor/graphql/product/resolvers.py b/saleor/graphql/product/resolvers.py
index 4c69f5d84ed..9490f19fe99 100644
--- a/saleor/graphql/product/resolvers.py
+++ b/saleor/graphql/product/resolvers.py
@@ -13,7 +13,7 @@
 
 
 def resolve_attributes(info, category_id, query):
-    queryset = models.ProductAttribute.objects.prefetch_related('values')
+    queryset = models.Attribute.objects.prefetch_related('values')
     queryset = filter_by_query_param(queryset, query, ATTRIBUTES_SEARCH_FIELDS)
     if category_id:
         # Get attributes that are used with product types
diff --git a/saleor/graphql/product/types.py b/saleor/graphql/product/types.py
index 878105af7ec..712c86a01c0 100644
--- a/saleor/graphql/product/types.py
+++ b/saleor/graphql/product/types.py
@@ -22,7 +22,7 @@
 color_pattern = re.compile(COLOR_PATTERN)
 
 
-class ProductAttributeValueType(graphene.Enum):
+class AttributeValueType(graphene.Enum):
     COLOR = 'COLOR'
     GRADIENT = 'GRADIENT'
     URL = 'URL'
@@ -34,10 +34,10 @@ def resolve_attribute_list(attributes):
     values = list(attributes.values())
 
     attributes_map = {
-        att.pk: att for att in models.ProductAttribute.objects.filter(
+        att.pk: att for att in models.Attribute.objects.filter(
             pk__in=keys)}
     values_map = {
-        val.pk: val for val in models.AttributeChoiceValue.objects.filter(
+        val.pk: val for val in models.AttributeValue.objects.filter(
             pk__in=values)}
 
     attributes_list = [SelectedAttribute(
@@ -49,36 +49,36 @@ def resolve_attribute_list(attributes):
 
 def resolve_attribute_value_type(attribute_value):
     if color_pattern.match(attribute_value):
-        return ProductAttributeValueType.COLOR
+        return AttributeValueType.COLOR
     if 'gradient(' in attribute_value:
-        return ProductAttributeValueType.GRADIENT
+        return AttributeValueType.GRADIENT
     if '://' in attribute_value:
-        return ProductAttributeValueType.URL
-    return ProductAttributeValueType.STRING
+        return AttributeValueType.URL
+    return AttributeValueType.STRING
 
 
-class ProductAttributeValue(CountableDjangoObjectType):
+class AttributeValue(CountableDjangoObjectType):
     name = graphene.String(description='Visible name for display purposes.')
     slug = graphene.String(
         description='Internal representation of an attribute name.')
-    type = ProductAttributeValueType(description='Type of value.')
+    type = AttributeValueType(description='Type of value.')
 
     class Meta:
         description = 'Represents a value of an attribute.'
         exclude_fields = ['attribute']
         interfaces = [relay.Node]
-        model = models.AttributeChoiceValue
+        model = models.AttributeValue
 
     def resolve_type(self, info):
         return resolve_attribute_value_type(self.value)
 
 
-class ProductAttribute(CountableDjangoObjectType):
+class Attribute(CountableDjangoObjectType):
     name = graphene.String(description='Visible name for display purposes.')
     slug = graphene.String(
         description='Internal representation of an attribute name.')
     values = graphene.List(
-        ProductAttributeValue, description='List of attribute\'s values.')
+        AttributeValue, description='List of attribute\'s values.')
 
     class Meta:
         description = """Custom attribute of a product. Attributes can be
@@ -86,7 +86,7 @@ class Meta:
         exclude_fields = ['product_types', 'product_variant_types']
         interfaces = [relay.Node]
         filter_fields = ['id', 'slug']
-        model = models.ProductAttribute
+        model = models.Attribute
 
     def resolve_values(self, info):
         return self.values.all()
@@ -99,14 +99,14 @@ class Margin(graphene.ObjectType):
 
 class SelectedAttribute(graphene.ObjectType):
     attribute = graphene.Field(
-        ProductAttribute,
+        Attribute,
         default_value=None, description='Name of an attribute')
     value = graphene.Field(
-        ProductAttributeValue,
+        AttributeValue,
         default_value=None, description='Value of an attribute.')
 
     class Meta:
-        description = 'Represents a custom product attribute.'
+        description = 'Represents a custom attribute.'
 
 
 class ProductVariant(CountableDjangoObjectType):
@@ -195,7 +195,7 @@ class Product(CountableDjangoObjectType):
         applied).""")
     attributes = graphene.List(
         SelectedAttribute,
-        description='List of product attributes assigned to this product.')
+        description='List of attributes assigned to this product.')
     purchase_cost = graphene.Field(MoneyRange)
     margin = graphene.Field(Margin)
     image_by_id = graphene.Field(
diff --git a/saleor/graphql/product/utils.py b/saleor/graphql/product/utils.py
index 6434486239a..8d196734f3d 100644
--- a/saleor/graphql/product/utils.py
+++ b/saleor/graphql/product/utils.py
@@ -1,7 +1,6 @@
 from django.utils.text import slugify
 
-from ...product.models import (
-    AttributeChoiceValue, ProductAttribute, ProductVariant)
+from ...product.models import Attribute, AttributeValue, ProductVariant
 from ...product.utils.attributes import get_name_from_attributes
 
 
@@ -16,7 +15,7 @@ def attributes_to_hstore(attribute_value_input, attributes_queryset):
 
     attributes_hstore = {}
     values_map = dict(
-        AttributeChoiceValue.objects.values_list('slug', 'id'))
+        AttributeValue.objects.values_list('slug', 'id'))
 
     for attribute in attribute_value_input:
         attr_slug = attribute.get('slug')
@@ -33,9 +32,9 @@ def attributes_to_hstore(attribute_value_input, attributes_queryset):
         value_id = values_map.get(value)
 
         if value_id is None:
-            # `value_id` was not found; create a new AttributeChoiceValue
+            # `value_id` was not found; create a new AttributeValue
             # instance from the provided `value`.
-            attr_instance = ProductAttribute.objects.get(slug=attr_slug)
+            attr_instance = Attribute.objects.get(slug=attr_slug)
             obj = attr_instance.values.get_or_create(
                 name=value, slug=slugify(value))[0]
             value_id = obj.pk
diff --git a/saleor/graphql/schema.graphql b/saleor/graphql/schema.graphql
index 9ffa771f1bc..fabf938b9e8 100644
--- a/saleor/graphql/schema.graphql
+++ b/saleor/graphql/schema.graphql
@@ -355,40 +355,94 @@ type AssignNavigation {
   menu: Menu
 }
 
-type AttributeChoiceValueCreate {
+type Attribute implements Node {
+  id: ID!
+  slug: String
+  name: String
+  values: [AttributeValue]
+}
+
+type AttributeCountableConnection {
+  pageInfo: PageInfo!
+  edges: [AttributeCountableEdge!]!
+  totalCount: Int
+}
+
+type AttributeCountableEdge {
+  node: Attribute!
+  cursor: String!
+}
+
+type AttributeCreate {
   errors: [Error]
-  attributeChoiceValue: ProductAttributeValue
+  attribute: Attribute
 }
 
-type AttributeChoiceValueDelete {
+type AttributeDelete {
   errors: [Error]
-  attributeChoiceValue: ProductAttributeValue
+  attribute: Attribute
 }
 
-input AttributeChoiceValueInput {
-  attribute: ID
-  slug: String!
-  name: String!
+scalar AttributeScalar
+
+type AttributeUpdate {
+  errors: [Error]
+  attribute: Attribute
+}
+
+type AttributeValue implements Node {
+  id: ID!
+  sortOrder: Int!
+  name: String
   value: String!
+  slug: String
+  type: AttributeValueType
 }
 
-type AttributeChoiceValueUpdate {
+type AttributeValueCreate {
   errors: [Error]
-  attributeChoiceValue: ProductAttributeValue
+  attributeValue: AttributeValue
 }
 
-input AttributeChoiceValueUpdateInput {
+input AttributeValueCreateInput {
+  attribute: ID
   slug: String!
   name: String!
+  value: String!
 }
 
-scalar AttributeScalar
+type AttributeValueDelete {
+  errors: [Error]
+  attributeValue: AttributeValue
+}
 
 input AttributeValueInput {
   slug: String!
   value: String!
 }
 
+enum AttributeValueType {
+  COLOR
+  GRADIENT
+  URL
+  STRING
+}
+
+type AttributeValueUpdate {
+  errors: [Error]
+  attributeValue: AttributeValue
+}
+
+input AttributeValueUpdateInput {
+  slug: String!
+  name: String!
+}
+
+input AttributesInput {
+  slug: String!
+  name: String!
+}
+
 type AuthorizationKey {
   name: String!
   key: String!
@@ -821,9 +875,9 @@ type Mutations {
   tokenVerify(token: String): VerifyToken
   setPassword(id: ID!, input: SetPasswordInput!): SetPassword
   passwordReset(email: String!): PasswordReset
-  attributeChoiceValueCreate(input: AttributeChoiceValueInput!): AttributeChoiceValueCreate
-  attributeChoiceValueDelete(id: ID!): AttributeChoiceValueDelete
-  attributeChoiceValueUpdate(id: ID!, input: AttributeChoiceValueUpdateInput!): AttributeChoiceValueUpdate
+  attributeValueCreate(input: AttributeValueCreateInput!): AttributeValueCreate
+  attributeValueDelete(id: ID!): AttributeValueDelete
+  attributeValueUpdate(id: ID!, input: AttributeValueUpdateInput!): AttributeValueUpdate
   categoryCreate(input: CategoryInput!): CategoryCreate
   categoryDelete(id: ID!): CategoryDelete
   categoryUpdate(id: ID!, input: CategoryInput!): CategoryUpdate
@@ -867,9 +921,9 @@ type Mutations {
   pageCreate(input: PageInput!): PageCreate
   pageDelete(id: ID!): PageDelete
   pageUpdate(id: ID!, input: PageInput!): PageUpdate
-  productAttributeCreate(input: ProductAttributesInput!): ProductAttributeCreate
-  productAttributeDelete(id: ID!): ProductAttributeDelete
-  productAttributeUpdate(id: ID!, input: ProductAttributesInput!): ProductAttributeUpdate
+  attributeCreate(input: AttributesInput!): AttributeCreate
+  attributeDelete(id: ID!): AttributeDelete
+  attributeUpdate(id: ID!, input: AttributesInput!): AttributeUpdate
   productCreate(input: ProductCreateInput!): ProductCreate
   productDelete(id: ID!): ProductDelete
   productUpdate(id: ID!, input: ProductInput!): ProductUpdate
@@ -1200,60 +1254,6 @@ type Product implements Node {
   imageById(id: ID): ProductImage
 }
 
-type ProductAttribute implements Node {
-  id: ID!
-  slug: String
-  name: String
-  values: [ProductAttributeValue]
-}
-
-type ProductAttributeCountableConnection {
-  pageInfo: PageInfo!
-  edges: [ProductAttributeCountableEdge!]!
-  totalCount: Int
-}
-
-type ProductAttributeCountableEdge {
-  node: ProductAttribute!
-  cursor: String!
-}
-
-type ProductAttributeCreate {
-  errors: [Error]
-  productAttribute: ProductAttribute
-}
-
-type ProductAttributeDelete {
-  errors: [Error]
-  productAttribute: ProductAttribute
-}
-
-type ProductAttributeUpdate {
-  errors: [Error]
-  productAttribute: ProductAttribute
-}
-
-type ProductAttributeValue implements Node {
-  id: ID!
-  sortOrder: Int!
-  name: String
-  value: String!
-  slug: String
-  type: ProductAttributeValueType
-}
-
-enum ProductAttributeValueType {
-  COLOR
-  GRADIENT
-  URL
-  STRING
-}
-
-input ProductAttributesInput {
-  slug: String!
-  name: String!
-}
-
 type ProductAvailability {
   available: Boolean
   onSale: Boolean
@@ -1372,8 +1372,8 @@ type ProductType implements Node {
   id: ID!
   name: String!
   hasVariants: Boolean!
-  productAttributes(before: String, after: String, first: Int, last: Int, id: ID, slug: String): ProductAttributeCountableConnection
-  variantAttributes(before: String, after: String, first: Int, last: Int, id: ID, slug: String): ProductAttributeCountableConnection
+  productAttributes(before: String, after: String, first: Int, last: Int, id: ID, slug: String): AttributeCountableConnection
+  variantAttributes(before: String, after: String, first: Int, last: Int, id: ID, slug: String): AttributeCountableConnection
   isShippingRequired: Boolean!
   taxRate: TaxRateType
   weight: Weight
@@ -1488,7 +1488,7 @@ type ProductVariantUpdate {
 
 type Query {
   addressValidator(input: AddressValidationInput!): AddressValidationData
-  attributes(query: String, inCategory: ID, before: String, after: String, first: Int, last: Int, id: ID, slug: String): ProductAttributeCountableConnection
+  attributes(query: String, inCategory: ID, before: String, after: String, first: Int, last: Int, id: ID, slug: String): AttributeCountableConnection
   categories(query: String, level: Int, before: String, after: String, first: Int, last: Int, id: ID, name: String): CategoryCountableConnection
   category(id: ID): Category
   collection(id: ID): Collection
@@ -1580,8 +1580,8 @@ type SaleUpdate {
 }
 
 type SelectedAttribute {
-  attribute: ProductAttribute
-  value: ProductAttributeValue
+  attribute: Attribute
+  value: AttributeValue
 }
 
 input SeoInput {
diff --git a/saleor/product/filters.py b/saleor/product/filters.py
index 45c29b3a568..9facd6ed7e6 100644
--- a/saleor/product/filters.py
+++ b/saleor/product/filters.py
@@ -6,7 +6,7 @@
 from django_filters import MultipleChoiceFilter, OrderingFilter, RangeFilter
 
 from ..core.filters import SortedFilterSet
-from .models import Product, ProductAttribute
+from .models import Attribute, Product
 
 SORT_BY_FIELDS = OrderedDict([
     ('name', pgettext_lazy('Product list sorting option', 'name')),
@@ -39,12 +39,12 @@ def _get_attributes(self):
         q_product_attributes = self._get_product_attributes_lookup()
         q_variant_attributes = self._get_variant_attributes_lookup()
         product_attributes = (
-            ProductAttribute.objects.all()
+            Attribute.objects.all()
             .prefetch_related('translations', 'values__translations')
             .filter(q_product_attributes)
             .distinct())
         variant_attributes = (
-            ProductAttribute.objects.all()
+            Attribute.objects.all()
             .prefetch_related('translations', 'values__translations')
             .filter(q_variant_attributes)
             .distinct())
diff --git a/saleor/product/migrations/0072_auto_20180925_1048.py b/saleor/product/migrations/0072_auto_20180925_1048.py
new file mode 100644
index 00000000000..1baba37328a
--- /dev/null
+++ b/saleor/product/migrations/0072_auto_20180925_1048.py
@@ -0,0 +1,47 @@
+# Generated by Django 2.0.8 on 2018-09-25 15:48
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('product', '0071_attributechoicevalue_value'),
+    ]
+
+    operations = [
+        migrations.RenameModel(
+            old_name='ProductAttribute',
+            new_name='Attribute',
+        ),
+        migrations.RenameModel(
+            old_name='AttributeChoiceValueTranslation',
+            new_name='AttributeValueTranslation',
+        ),
+        migrations.RenameModel(
+            old_name='AttributeChoiceValue',
+            new_name='AttributeValue',
+        ),
+        migrations.RenameModel(
+            old_name='ProductAttributeTranslation',
+            new_name='AttributeTranslation',
+        ),
+        migrations.RenameField(
+            model_name='attributetranslation',
+            old_name='product_attribute',
+            new_name='attribute',
+        ),
+        migrations.RenameField(
+            model_name='attributevaluetranslation',
+            old_name='attribute_choice_value',
+            new_name='attribute_value',
+        ),
+        migrations.AlterUniqueTogether(
+            name='attributetranslation',
+            unique_together={('language_code', 'attribute')},
+        ),
+        migrations.AlterUniqueTogether(
+            name='attributevaluetranslation',
+            unique_together={('language_code', 'attribute_value')},
+        ),
+    ]
diff --git a/saleor/product/models.py b/saleor/product/models.py
index e8031c833b9..dc1c2336181 100644
--- a/saleor/product/models.py
+++ b/saleor/product/models.py
@@ -76,9 +76,9 @@ class ProductType(models.Model):
     name = models.CharField(max_length=128)
     has_variants = models.BooleanField(default=True)
     product_attributes = models.ManyToManyField(
-        'ProductAttribute', related_name='product_types', blank=True)
+        'Attribute', related_name='product_types', blank=True)
     variant_attributes = models.ManyToManyField(
-        'ProductAttribute', related_name='product_variant_types', blank=True)
+        'Attribute', related_name='product_variant_types', blank=True)
     is_shipping_required = models.BooleanField(default=False)
     tax_rate = models.CharField(
         max_length=128, default=DEFAULT_TAX_RATE_NAME, blank=True,
@@ -317,7 +317,7 @@ def __str__(self):
         return self.name or str(self.product_variant)
 
 
-class ProductAttribute(models.Model):
+class Attribute(models.Model):
     slug = models.SlugField(max_length=50, unique=True)
     name = models.CharField(max_length=100)
 
@@ -336,31 +336,31 @@ def has_values(self):
         return self.values.exists()
 
 
-class ProductAttributeTranslation(models.Model):
+class AttributeTranslation(models.Model):
     language_code = models.CharField(max_length=10)
-    product_attribute = models.ForeignKey(
-        ProductAttribute, related_name='translations',
+    attribute = models.ForeignKey(
+        Attribute, related_name='translations',
         on_delete=models.CASCADE)
     name = models.CharField(max_length=100)
 
     class Meta:
-        unique_together = (('language_code', 'product_attribute'),)
+        unique_together = (('language_code', 'attribute'),)
 
     def __repr__(self):
         class_ = type(self)
         return '%s(pk=%r, name=%r, attribute_pk=%r)' % (
-            class_.__name__, self.pk, self.name, self.product_attribute_id)
+            class_.__name__, self.pk, self.name, self.attribute_id)
 
     def __str__(self):
         return self.name
 
 
-class AttributeChoiceValue(SortableModel):
+class AttributeValue(SortableModel):
     name = models.CharField(max_length=100)
     value = models.CharField(max_length=100, default='')
     slug = models.SlugField(max_length=100)
     attribute = models.ForeignKey(
-        ProductAttribute, related_name='values', on_delete=models.CASCADE)
+        Attribute, related_name='values', on_delete=models.CASCADE)
 
     translated = TranslationProxy()
 
@@ -375,21 +375,21 @@ def get_ordering_queryset(self):
         return self.attribute.values.all()
 
 
-class AttributeChoiceValueTranslation(models.Model):
+class AttributeValueTranslation(models.Model):
     language_code = models.CharField(max_length=10)
-    attribute_choice_value = models.ForeignKey(
-        AttributeChoiceValue, related_name='translations',
+    attribute_value = models.ForeignKey(
+        AttributeValue, related_name='translations',
         on_delete=models.CASCADE)
     name = models.CharField(max_length=100)
 
     class Meta:
-        unique_together = (('language_code', 'attribute_choice_value'),)
+        unique_together = (('language_code', 'attribute_value'),)
 
     def __repr__(self):
         class_ = type(self)
-        return '%s(pk=%r, name=%r, attribute_choice_value_pk=%r)' % (
+        return '%s(pk=%r, name=%r, attribute_value_pk=%r)' % (
             class_.__name__, self.pk, self.name,
-            self.attribute_choice_value_id)
+            self.attribute_value_id)
 
     def __str__(self):
         return self.name
diff --git a/saleor/product/utils/attributes.py b/saleor/product/utils/attributes.py
index 287d382b526..52e3a866902 100644
--- a/saleor/product/utils/attributes.py
+++ b/saleor/product/utils/attributes.py
@@ -1,6 +1,6 @@
 def get_product_attributes_data(product):
     """Returns attributes associated with the product,
-    as dict of ProductAttribute: AttributeChoiceValue values.
+    as dict of Attribute: AttributeValue values.
     """
     attributes = product.product_type.product_attributes.all()
     attributes_map = {
@@ -19,10 +19,10 @@ def get_name_from_attributes(variant, attributes):
 
 def get_attributes_display_map(obj, attributes):
     """Returns attributes associated with an object,
-    as dict of ProductAttribute: AttributeChoiceValue values.
+    as dict of Attribute: AttributeValue values.
 
     Args:
-        attributes: ProductAttribute Iterable
+        attributes: Attribute Iterable
     """
     display_map = {}
     for attribute in attributes:
@@ -34,14 +34,14 @@ def get_attributes_display_map(obj, attributes):
 
 
 def generate_name_from_values(attributes_dict):
-    """Generates name from AttributeChoiceValues. Attributes dict is sorted,
+    """Generates name from AttributeValues. Attributes dict is sorted,
     as attributes order should be kept within each save.
 
     Args:
-        attributes_dict: dict of attribute_pk: AttributeChoiceValue values
+        attributes_dict: dict of attribute_pk: AttributeValue values
     """
     return ' / '.join(
-        str(attributechoice_value)
-        for attribute_pk, attributechoice_value in sorted(
+        str(attribute_value)
+        for attribute_pk, attribute_value in sorted(
             attributes_dict.items(),
             key=lambda x: x[0]))
diff --git a/saleor/product/views.py b/saleor/product/views.py
index 4aa37efcf0a..ccecdcb1b38 100644
--- a/saleor/product/views.py
+++ b/saleor/product/views.py
@@ -13,8 +13,8 @@
 from .models import Category
 from .utils import (
     collections_visible_to_user, get_product_images, get_product_list_context,
-    handle_cart_form, products_for_cart, products_with_details,
-    products_for_products_list)
+    handle_cart_form, products_for_cart, products_for_products_list,
+    products_with_details)
 from .utils.attributes import get_product_attributes_data
 from .utils.availability import get_availability
 from .utils.variants_picker import get_variant_picker_data
diff --git a/saleor/static/dashboard-next/productTypes/types/ProductTypeCreate.ts b/saleor/static/dashboard-next/productTypes/types/ProductTypeCreate.ts
index 924329220ff..fde6f06fc42 100644
--- a/saleor/static/dashboard-next/productTypes/types/ProductTypeCreate.ts
+++ b/saleor/static/dashboard-next/productTypes/types/ProductTypeCreate.ts
@@ -14,36 +14,36 @@ export interface ProductTypeCreate_productTypeCreate_errors {
 }
 
 export interface ProductTypeCreate_productTypeCreate_productType_productAttributes_edges_node {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   slug: string | null;
   name: string | null;
 }
 
 export interface ProductTypeCreate_productTypeCreate_productType_productAttributes_edges {
-  __typename: "ProductAttributeCountableEdge";
+  __typename: "AttributeCountableEdge";
   node: ProductTypeCreate_productTypeCreate_productType_productAttributes_edges_node;
 }
 
 export interface ProductTypeCreate_productTypeCreate_productType_productAttributes {
-  __typename: "ProductAttributeCountableConnection";
+  __typename: "AttributeCountableConnection";
   edges: ProductTypeCreate_productTypeCreate_productType_productAttributes_edges[];
 }
 
 export interface ProductTypeCreate_productTypeCreate_productType_variantAttributes_edges_node {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   slug: string | null;
   name: string | null;
 }
 
 export interface ProductTypeCreate_productTypeCreate_productType_variantAttributes_edges {
-  __typename: "ProductAttributeCountableEdge";
+  __typename: "AttributeCountableEdge";
   node: ProductTypeCreate_productTypeCreate_productType_variantAttributes_edges_node;
 }
 
 export interface ProductTypeCreate_productTypeCreate_productType_variantAttributes {
-  __typename: "ProductAttributeCountableConnection";
+  __typename: "AttributeCountableConnection";
   edges: ProductTypeCreate_productTypeCreate_productType_variantAttributes_edges[];
 }
 
diff --git a/saleor/static/dashboard-next/productTypes/types/ProductTypeDetails.ts b/saleor/static/dashboard-next/productTypes/types/ProductTypeDetails.ts
index d9b22db01c3..54824fbc404 100644
--- a/saleor/static/dashboard-next/productTypes/types/ProductTypeDetails.ts
+++ b/saleor/static/dashboard-next/productTypes/types/ProductTypeDetails.ts
@@ -8,36 +8,36 @@ import { TaxRateType } from "./../../types/globalTypes";
 // ====================================================
 
 export interface ProductTypeDetails_productType_productAttributes_edges_node {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   slug: string | null;
   name: string | null;
 }
 
 export interface ProductTypeDetails_productType_productAttributes_edges {
-  __typename: "ProductAttributeCountableEdge";
+  __typename: "AttributeCountableEdge";
   node: ProductTypeDetails_productType_productAttributes_edges_node;
 }
 
 export interface ProductTypeDetails_productType_productAttributes {
-  __typename: "ProductAttributeCountableConnection";
+  __typename: "AttributeCountableConnection";
   edges: ProductTypeDetails_productType_productAttributes_edges[];
 }
 
 export interface ProductTypeDetails_productType_variantAttributes_edges_node {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   slug: string | null;
   name: string | null;
 }
 
 export interface ProductTypeDetails_productType_variantAttributes_edges {
-  __typename: "ProductAttributeCountableEdge";
+  __typename: "AttributeCountableEdge";
   node: ProductTypeDetails_productType_variantAttributes_edges_node;
 }
 
 export interface ProductTypeDetails_productType_variantAttributes {
-  __typename: "ProductAttributeCountableConnection";
+  __typename: "AttributeCountableConnection";
   edges: ProductTypeDetails_productType_variantAttributes_edges[];
 }
 
diff --git a/saleor/static/dashboard-next/productTypes/types/ProductTypeList.ts b/saleor/static/dashboard-next/productTypes/types/ProductTypeList.ts
index 77c87fb0f39..a8e457fb3fb 100644
--- a/saleor/static/dashboard-next/productTypes/types/ProductTypeList.ts
+++ b/saleor/static/dashboard-next/productTypes/types/ProductTypeList.ts
@@ -6,34 +6,34 @@
 // ====================================================
 
 export interface ProductTypeList_productTypes_edges_node_productAttributes_edges_node {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   name: string | null;
 }
 
 export interface ProductTypeList_productTypes_edges_node_productAttributes_edges {
-  __typename: "ProductAttributeCountableEdge";
+  __typename: "AttributeCountableEdge";
   node: ProductTypeList_productTypes_edges_node_productAttributes_edges_node;
 }
 
 export interface ProductTypeList_productTypes_edges_node_productAttributes {
-  __typename: "ProductAttributeCountableConnection";
+  __typename: "AttributeCountableConnection";
   edges: ProductTypeList_productTypes_edges_node_productAttributes_edges[];
 }
 
 export interface ProductTypeList_productTypes_edges_node_variantAttributes_edges_node {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   name: string | null;
 }
 
 export interface ProductTypeList_productTypes_edges_node_variantAttributes_edges {
-  __typename: "ProductAttributeCountableEdge";
+  __typename: "AttributeCountableEdge";
   node: ProductTypeList_productTypes_edges_node_variantAttributes_edges_node;
 }
 
 export interface ProductTypeList_productTypes_edges_node_variantAttributes {
-  __typename: "ProductAttributeCountableConnection";
+  __typename: "AttributeCountableConnection";
   edges: ProductTypeList_productTypes_edges_node_variantAttributes_edges[];
 }
 
diff --git a/saleor/static/dashboard-next/productTypes/types/ProductTypeUpdate.ts b/saleor/static/dashboard-next/productTypes/types/ProductTypeUpdate.ts
index 500e8205f5b..ca44d9cca7c 100644
--- a/saleor/static/dashboard-next/productTypes/types/ProductTypeUpdate.ts
+++ b/saleor/static/dashboard-next/productTypes/types/ProductTypeUpdate.ts
@@ -14,36 +14,36 @@ export interface ProductTypeUpdate_productTypeUpdate_errors {
 }
 
 export interface ProductTypeUpdate_productTypeUpdate_productType_productAttributes_edges_node {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   slug: string | null;
   name: string | null;
 }
 
 export interface ProductTypeUpdate_productTypeUpdate_productType_productAttributes_edges {
-  __typename: "ProductAttributeCountableEdge";
+  __typename: "AttributeCountableEdge";
   node: ProductTypeUpdate_productTypeUpdate_productType_productAttributes_edges_node;
 }
 
 export interface ProductTypeUpdate_productTypeUpdate_productType_productAttributes {
-  __typename: "ProductAttributeCountableConnection";
+  __typename: "AttributeCountableConnection";
   edges: ProductTypeUpdate_productTypeUpdate_productType_productAttributes_edges[];
 }
 
 export interface ProductTypeUpdate_productTypeUpdate_productType_variantAttributes_edges_node {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   slug: string | null;
   name: string | null;
 }
 
 export interface ProductTypeUpdate_productTypeUpdate_productType_variantAttributes_edges {
-  __typename: "ProductAttributeCountableEdge";
+  __typename: "AttributeCountableEdge";
   node: ProductTypeUpdate_productTypeUpdate_productType_variantAttributes_edges_node;
 }
 
 export interface ProductTypeUpdate_productTypeUpdate_productType_variantAttributes {
-  __typename: "ProductAttributeCountableConnection";
+  __typename: "AttributeCountableConnection";
   edges: ProductTypeUpdate_productTypeUpdate_productType_variantAttributes_edges[];
 }
 
diff --git a/saleor/static/dashboard-next/productTypes/types/SearchAttribute.ts b/saleor/static/dashboard-next/productTypes/types/SearchAttribute.ts
index 8c5362a6fd2..560abb095d2 100644
--- a/saleor/static/dashboard-next/productTypes/types/SearchAttribute.ts
+++ b/saleor/static/dashboard-next/productTypes/types/SearchAttribute.ts
@@ -6,19 +6,19 @@
 // ====================================================
 
 export interface SearchAttribute_attributes_edges_node {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   slug: string | null;
   name: string | null;
 }
 
 export interface SearchAttribute_attributes_edges {
-  __typename: "ProductAttributeCountableEdge";
+  __typename: "AttributeCountableEdge";
   node: SearchAttribute_attributes_edges_node;
 }
 
 export interface SearchAttribute_attributes {
-  __typename: "ProductAttributeCountableConnection";
+  __typename: "AttributeCountableConnection";
   edges: SearchAttribute_attributes_edges[];
 }
 
diff --git a/saleor/static/dashboard-next/products/components/ProductAttributesForm/ProductAttributesForm.tsx b/saleor/static/dashboard-next/products/components/ProductAttributesForm/ProductAttributesForm.tsx
index a06d19a6161..ddcce453e22 100644
--- a/saleor/static/dashboard-next/products/components/ProductAttributesForm/ProductAttributesForm.tsx
+++ b/saleor/static/dashboard-next/products/components/ProductAttributesForm/ProductAttributesForm.tsx
@@ -10,7 +10,7 @@ import SingleSelectField from "../../../components/SingleSelectField";
 import Skeleton from "../../../components/Skeleton";
 import i18n from "../../../i18n";
 
-interface ProductAttributesFormProps {
+interface AttributesFormProps {
   attributes?: Array<{
     attribute: AttributeType;
     value: AttributeValueType;
@@ -22,8 +22,8 @@ interface ProductAttributesFormProps {
   onChange(event: any);
 }
 
-export const ProductAttributesForm: React.StatelessComponent<
-  ProductAttributesFormProps
+export const AttributesForm: React.StatelessComponent<
+  AttributesFormProps
 > = ({ attributes, data, disabled, onChange }) => (
   <Card>
     <PageHeader title={i18n.t("Attributes")} />
@@ -52,4 +52,4 @@ export const ProductAttributesForm: React.StatelessComponent<
     </CardContent>
   </Card>
 );
-export default ProductAttributesForm;
+export default AttributesForm;
diff --git a/saleor/static/dashboard-next/products/components/ProductAttributesForm/index.ts b/saleor/static/dashboard-next/products/components/ProductAttributesForm/index.ts
index 724931497fd..e6de659863d 100644
--- a/saleor/static/dashboard-next/products/components/ProductAttributesForm/index.ts
+++ b/saleor/static/dashboard-next/products/components/ProductAttributesForm/index.ts
@@ -1,2 +1,2 @@
-export { default } from "./ProductAttributesForm";
-export * from "./ProductAttributesForm";
+export { default } from "./AttributesForm";
+export * from "./AttributesForm";
diff --git a/saleor/static/dashboard-next/products/components/ProductOrganization/ProductOrganization.tsx b/saleor/static/dashboard-next/products/components/ProductOrganization/ProductOrganization.tsx
index 5b1db708b2e..206c7541532 100644
--- a/saleor/static/dashboard-next/products/components/ProductOrganization/ProductOrganization.tsx
+++ b/saleor/static/dashboard-next/products/components/ProductOrganization/ProductOrganization.tsx
@@ -133,7 +133,7 @@ const ProductOrganization = decorate<ProductOrganizationProps>(
         }
       });
     };
-    const handleProductAttributeValueSelect = (
+    const handleAttributeValueSelect = (
       event: React.ChangeEvent<{
         name: string;
         value: {
@@ -207,7 +207,7 @@ const ProductOrganization = decorate<ProductOrganizationProps>(
                     disabled={disabled}
                     name={item.slug}
                     label={getAttributeName(item.slug)}
-                    onChange={handleProductAttributeValueSelect}
+                    onChange={handleAttributeValueSelect}
                     value={getAttributeValue(item.slug)}
                     choices={getAttributeValues(item.slug).map(v => ({
                       label: v.name,
diff --git a/saleor/static/dashboard-next/products/components/ProductVariantAttributes/ProductVariantAttributes.tsx b/saleor/static/dashboard-next/products/components/ProductVariantAttributes/ProductVariantAttributes.tsx
index 6a0407f5723..bbe1151da67 100644
--- a/saleor/static/dashboard-next/products/components/ProductVariantAttributes/ProductVariantAttributes.tsx
+++ b/saleor/static/dashboard-next/products/components/ProductVariantAttributes/ProductVariantAttributes.tsx
@@ -80,7 +80,7 @@ const ProductVariantAttributes = decorate<ProductVariantAttributesProps>(
                     }))
                   : [];
               };
-              const handleProductAttributeValueSelect = (
+              const handleAttributeValueSelect = (
                 event: React.ChangeEvent<{
                   name: string;
                   value: {
@@ -109,7 +109,7 @@ const ProductVariantAttributes = decorate<ProductVariantAttributesProps>(
                     disabled={disabled}
                     name={item.slug}
                     label={item.name}
-                    onChange={handleProductAttributeValueSelect}
+                    onChange={handleAttributeValueSelect}
                     value={getAttributeValue(item.slug)}
                     choices={getAttributeValues(item.slug)}
                     key={index}
diff --git a/saleor/static/dashboard-next/products/types/Product.ts b/saleor/static/dashboard-next/products/types/Product.ts
index c02bcc0fce0..550afb6b629 100644
--- a/saleor/static/dashboard-next/products/types/Product.ts
+++ b/saleor/static/dashboard-next/products/types/Product.ts
@@ -58,13 +58,13 @@ export interface Product_purchaseCost {
 }
 
 export interface Product_attributes_attribute_values {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   name: string | null;
   slug: string | null;
 }
 
 export interface Product_attributes_attribute {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   slug: string | null;
   name: string | null;
@@ -72,7 +72,7 @@ export interface Product_attributes_attribute {
 }
 
 export interface Product_attributes_value {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   name: string | null;
   slug: string | null;
diff --git a/saleor/static/dashboard-next/products/types/ProductCreate.ts b/saleor/static/dashboard-next/products/types/ProductCreate.ts
index c9d454b87b0..f72d95f33c8 100644
--- a/saleor/static/dashboard-next/products/types/ProductCreate.ts
+++ b/saleor/static/dashboard-next/products/types/ProductCreate.ts
@@ -66,13 +66,13 @@ export interface ProductCreate_productCreate_product_purchaseCost {
 }
 
 export interface ProductCreate_productCreate_product_attributes_attribute_values {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   name: string | null;
   slug: string | null;
 }
 
 export interface ProductCreate_productCreate_product_attributes_attribute {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   slug: string | null;
   name: string | null;
@@ -80,7 +80,7 @@ export interface ProductCreate_productCreate_product_attributes_attribute {
 }
 
 export interface ProductCreate_productCreate_product_attributes_value {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   name: string | null;
   slug: string | null;
diff --git a/saleor/static/dashboard-next/products/types/ProductCreateData.ts b/saleor/static/dashboard-next/products/types/ProductCreateData.ts
index c9c0f2fc915..447696091ca 100644
--- a/saleor/static/dashboard-next/products/types/ProductCreateData.ts
+++ b/saleor/static/dashboard-next/products/types/ProductCreateData.ts
@@ -6,7 +6,7 @@
 // ====================================================
 
 export interface ProductCreateData_productTypes_edges_node_productAttributes_edges_node_values {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   sortOrder: number;
   name: string | null;
@@ -14,7 +14,7 @@ export interface ProductCreateData_productTypes_edges_node_productAttributes_edg
 }
 
 export interface ProductCreateData_productTypes_edges_node_productAttributes_edges_node {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   slug: string | null;
   name: string | null;
@@ -22,12 +22,12 @@ export interface ProductCreateData_productTypes_edges_node_productAttributes_edg
 }
 
 export interface ProductCreateData_productTypes_edges_node_productAttributes_edges {
-  __typename: "ProductAttributeCountableEdge";
+  __typename: "AttributeCountableEdge";
   node: ProductCreateData_productTypes_edges_node_productAttributes_edges_node;
 }
 
 export interface ProductCreateData_productTypes_edges_node_productAttributes {
-  __typename: "ProductAttributeCountableConnection";
+  __typename: "AttributeCountableConnection";
   edges: ProductCreateData_productTypes_edges_node_productAttributes_edges[];
 }
 
diff --git a/saleor/static/dashboard-next/products/types/ProductDetails.ts b/saleor/static/dashboard-next/products/types/ProductDetails.ts
index 3a8e7d173e2..df311260f58 100644
--- a/saleor/static/dashboard-next/products/types/ProductDetails.ts
+++ b/saleor/static/dashboard-next/products/types/ProductDetails.ts
@@ -58,13 +58,13 @@ export interface ProductDetails_product_purchaseCost {
 }
 
 export interface ProductDetails_product_attributes_attribute_values {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   name: string | null;
   slug: string | null;
 }
 
 export interface ProductDetails_product_attributes_attribute {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   slug: string | null;
   name: string | null;
@@ -72,7 +72,7 @@ export interface ProductDetails_product_attributes_attribute {
 }
 
 export interface ProductDetails_product_attributes_value {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   name: string | null;
   slug: string | null;
diff --git a/saleor/static/dashboard-next/products/types/ProductImageCreate.ts b/saleor/static/dashboard-next/products/types/ProductImageCreate.ts
index ae04ca3a0d5..77b6bece2fe 100644
--- a/saleor/static/dashboard-next/products/types/ProductImageCreate.ts
+++ b/saleor/static/dashboard-next/products/types/ProductImageCreate.ts
@@ -64,13 +64,13 @@ export interface ProductImageCreate_productImageCreate_product_purchaseCost {
 }
 
 export interface ProductImageCreate_productImageCreate_product_attributes_attribute_values {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   name: string | null;
   slug: string | null;
 }
 
 export interface ProductImageCreate_productImageCreate_product_attributes_attribute {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   slug: string | null;
   name: string | null;
@@ -78,7 +78,7 @@ export interface ProductImageCreate_productImageCreate_product_attributes_attrib
 }
 
 export interface ProductImageCreate_productImageCreate_product_attributes_value {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   name: string | null;
   slug: string | null;
diff --git a/saleor/static/dashboard-next/products/types/ProductImageUpdate.ts b/saleor/static/dashboard-next/products/types/ProductImageUpdate.ts
index d5268bdb7ce..bea80a0b89a 100644
--- a/saleor/static/dashboard-next/products/types/ProductImageUpdate.ts
+++ b/saleor/static/dashboard-next/products/types/ProductImageUpdate.ts
@@ -64,13 +64,13 @@ export interface ProductImageUpdate_productImageUpdate_product_purchaseCost {
 }
 
 export interface ProductImageUpdate_productImageUpdate_product_attributes_attribute_values {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   name: string | null;
   slug: string | null;
 }
 
 export interface ProductImageUpdate_productImageUpdate_product_attributes_attribute {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   slug: string | null;
   name: string | null;
@@ -78,7 +78,7 @@ export interface ProductImageUpdate_productImageUpdate_product_attributes_attrib
 }
 
 export interface ProductImageUpdate_productImageUpdate_product_attributes_value {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   name: string | null;
   slug: string | null;
diff --git a/saleor/static/dashboard-next/products/types/ProductUpdate.ts b/saleor/static/dashboard-next/products/types/ProductUpdate.ts
index 12f4f98c794..4268c8469dd 100644
--- a/saleor/static/dashboard-next/products/types/ProductUpdate.ts
+++ b/saleor/static/dashboard-next/products/types/ProductUpdate.ts
@@ -66,13 +66,13 @@ export interface ProductUpdate_productUpdate_product_purchaseCost {
 }
 
 export interface ProductUpdate_productUpdate_product_attributes_attribute_values {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   name: string | null;
   slug: string | null;
 }
 
 export interface ProductUpdate_productUpdate_product_attributes_attribute {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   slug: string | null;
   name: string | null;
@@ -80,7 +80,7 @@ export interface ProductUpdate_productUpdate_product_attributes_attribute {
 }
 
 export interface ProductUpdate_productUpdate_product_attributes_value {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   name: string | null;
   slug: string | null;
diff --git a/saleor/static/dashboard-next/products/types/ProductVariant.ts b/saleor/static/dashboard-next/products/types/ProductVariant.ts
index 82c9ca3cc47..993b44f9437 100644
--- a/saleor/static/dashboard-next/products/types/ProductVariant.ts
+++ b/saleor/static/dashboard-next/products/types/ProductVariant.ts
@@ -6,14 +6,14 @@
 // ====================================================
 
 export interface ProductVariant_attributes_attribute_values {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   name: string | null;
   slug: string | null;
 }
 
 export interface ProductVariant_attributes_attribute {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   name: string | null;
   slug: string | null;
@@ -21,7 +21,7 @@ export interface ProductVariant_attributes_attribute {
 }
 
 export interface ProductVariant_attributes_value {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   name: string | null;
   slug: string | null;
diff --git a/saleor/static/dashboard-next/products/types/ProductVariantCreateData.ts b/saleor/static/dashboard-next/products/types/ProductVariantCreateData.ts
index 8500879f070..099503e4e47 100644
--- a/saleor/static/dashboard-next/products/types/ProductVariantCreateData.ts
+++ b/saleor/static/dashboard-next/products/types/ProductVariantCreateData.ts
@@ -23,7 +23,7 @@ export interface ProductVariantCreateData_product_images {
 }
 
 export interface ProductVariantCreateData_product_productType_variantAttributes_edges_node_values {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   sortOrder: number;
   name: string | null;
@@ -31,7 +31,7 @@ export interface ProductVariantCreateData_product_productType_variantAttributes_
 }
 
 export interface ProductVariantCreateData_product_productType_variantAttributes_edges_node {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   slug: string | null;
   name: string | null;
@@ -39,12 +39,12 @@ export interface ProductVariantCreateData_product_productType_variantAttributes_
 }
 
 export interface ProductVariantCreateData_product_productType_variantAttributes_edges {
-  __typename: "ProductAttributeCountableEdge";
+  __typename: "AttributeCountableEdge";
   node: ProductVariantCreateData_product_productType_variantAttributes_edges_node;
 }
 
 export interface ProductVariantCreateData_product_productType_variantAttributes {
-  __typename: "ProductAttributeCountableConnection";
+  __typename: "AttributeCountableConnection";
   edges: ProductVariantCreateData_product_productType_variantAttributes_edges[];
 }
 
diff --git a/saleor/static/dashboard-next/products/types/ProductVariantDetails.ts b/saleor/static/dashboard-next/products/types/ProductVariantDetails.ts
index 8bf747a48b5..5c3005bedb7 100644
--- a/saleor/static/dashboard-next/products/types/ProductVariantDetails.ts
+++ b/saleor/static/dashboard-next/products/types/ProductVariantDetails.ts
@@ -6,14 +6,14 @@
 // ====================================================
 
 export interface ProductVariantDetails_productVariant_attributes_attribute_values {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   name: string | null;
   slug: string | null;
 }
 
 export interface ProductVariantDetails_productVariant_attributes_attribute {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   name: string | null;
   slug: string | null;
@@ -21,7 +21,7 @@ export interface ProductVariantDetails_productVariant_attributes_attribute {
 }
 
 export interface ProductVariantDetails_productVariant_attributes_value {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   name: string | null;
   slug: string | null;
diff --git a/saleor/static/dashboard-next/products/types/VariantCreate.ts b/saleor/static/dashboard-next/products/types/VariantCreate.ts
index 59c275663a7..123eee96e9c 100644
--- a/saleor/static/dashboard-next/products/types/VariantCreate.ts
+++ b/saleor/static/dashboard-next/products/types/VariantCreate.ts
@@ -14,14 +14,14 @@ export interface VariantCreate_productVariantCreate_errors {
 }
 
 export interface VariantCreate_productVariantCreate_productVariant_attributes_attribute_values {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   name: string | null;
   slug: string | null;
 }
 
 export interface VariantCreate_productVariantCreate_productVariant_attributes_attribute {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   name: string | null;
   slug: string | null;
@@ -29,7 +29,7 @@ export interface VariantCreate_productVariantCreate_productVariant_attributes_at
 }
 
 export interface VariantCreate_productVariantCreate_productVariant_attributes_value {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   name: string | null;
   slug: string | null;
diff --git a/saleor/static/dashboard-next/products/types/VariantImageAssign.ts b/saleor/static/dashboard-next/products/types/VariantImageAssign.ts
index 3527f5a73ab..49aab2c2bf9 100644
--- a/saleor/static/dashboard-next/products/types/VariantImageAssign.ts
+++ b/saleor/static/dashboard-next/products/types/VariantImageAssign.ts
@@ -12,14 +12,14 @@ export interface VariantImageAssign_variantImageAssign_errors {
 }
 
 export interface VariantImageAssign_variantImageAssign_productVariant_attributes_attribute_values {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   name: string | null;
   slug: string | null;
 }
 
 export interface VariantImageAssign_variantImageAssign_productVariant_attributes_attribute {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   name: string | null;
   slug: string | null;
@@ -27,7 +27,7 @@ export interface VariantImageAssign_variantImageAssign_productVariant_attributes
 }
 
 export interface VariantImageAssign_variantImageAssign_productVariant_attributes_value {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   name: string | null;
   slug: string | null;
diff --git a/saleor/static/dashboard-next/products/types/VariantImageUnassign.ts b/saleor/static/dashboard-next/products/types/VariantImageUnassign.ts
index 0813a21abc8..e554bd59b28 100644
--- a/saleor/static/dashboard-next/products/types/VariantImageUnassign.ts
+++ b/saleor/static/dashboard-next/products/types/VariantImageUnassign.ts
@@ -12,14 +12,14 @@ export interface VariantImageUnassign_variantImageUnassign_errors {
 }
 
 export interface VariantImageUnassign_variantImageUnassign_productVariant_attributes_attribute_values {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   name: string | null;
   slug: string | null;
 }
 
 export interface VariantImageUnassign_variantImageUnassign_productVariant_attributes_attribute {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   name: string | null;
   slug: string | null;
@@ -27,7 +27,7 @@ export interface VariantImageUnassign_variantImageUnassign_productVariant_attrib
 }
 
 export interface VariantImageUnassign_variantImageUnassign_productVariant_attributes_value {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   name: string | null;
   slug: string | null;
diff --git a/saleor/static/dashboard-next/products/types/VariantUpdate.ts b/saleor/static/dashboard-next/products/types/VariantUpdate.ts
index 3d96df1c625..0067906753e 100644
--- a/saleor/static/dashboard-next/products/types/VariantUpdate.ts
+++ b/saleor/static/dashboard-next/products/types/VariantUpdate.ts
@@ -14,14 +14,14 @@ export interface VariantUpdate_productVariantUpdate_errors {
 }
 
 export interface VariantUpdate_productVariantUpdate_productVariant_attributes_attribute_values {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   name: string | null;
   slug: string | null;
 }
 
 export interface VariantUpdate_productVariantUpdate_productVariant_attributes_attribute {
-  __typename: "ProductAttribute";
+  __typename: "Attribute";
   id: string;
   name: string | null;
   slug: string | null;
@@ -29,7 +29,7 @@ export interface VariantUpdate_productVariantUpdate_productVariant_attributes_at
 }
 
 export interface VariantUpdate_productVariantUpdate_productVariant_attributes_value {
-  __typename: "ProductAttributeValue";
+  __typename: "AttributeValue";
   id: string;
   name: string | null;
   slug: string | null;
diff --git a/templates/dashboard/base.html b/templates/dashboard/base.html
index c773614949c..b869f819872 100644
--- a/templates/dashboard/base.html
+++ b/templates/dashboard/base.html
@@ -189,7 +189,7 @@
                       </a>
                     </li>
                     <li class="{% block menu_attributes_class %}{% endblock %}">
-                      <a href="{% url 'dashboard:product-attributes' %}">
+                      <a href="{% url 'dashboard:attributes' %}">
                         {% trans "Attributes" context "Dashboard attributes list" %}
                       </a>
                     </li>
diff --git a/templates/dashboard/product/product_attribute/detail.html b/templates/dashboard/product/attribute/detail.html
similarity index 74%
rename from templates/dashboard/product/product_attribute/detail.html
rename to templates/dashboard/product/attribute/detail.html
index 3b1621a25aa..135ab80457e 100644
--- a/templates/dashboard/product/product_attribute/detail.html
+++ b/templates/dashboard/product/attribute/detail.html
@@ -14,12 +14,12 @@
 {% block breadcrumbs %}
   <ul class="breadcrumbs breadcrumbs--history">
     <li>
-      <a href="{% url 'dashboard:product-attributes' %}" class="breadcrumbs--ellipsed-item">
+      <a href="{% url 'dashboard:attributes' %}" class="breadcrumbs--ellipsed-item">
       {% trans "Attributes" context "Attribute detail breadcrumbs" %}
       </a>
     </li>
     <li class="back-mobile">
-      <a href="{% url 'dashboard:product-attributes' %}">
+      <a href="{% url 'dashboard:attributes' %}">
         <svg data-src="{% static "dashboard/images/arrow-left.svg" %}" fill="#fff" width="20px" height="20px" />
       </a>
     </li>
@@ -44,10 +44,10 @@
           </span>
         </div>
         <div class="card-action">
-          <a class="btn-flat waves-effect" href="{% url "dashboard:product-attribute-update" attribute.pk %}">
+          <a class="btn-flat waves-effect" href="{% url "dashboard:attribute-update" attribute.pk %}">
             {% trans "Edit attribute" context "Attribute detail action" %}
           </a>
-          <a class="btn-flat waves-effect modal-trigger-custom" href="#base-modal" data-href="{% url 'dashboard:product-attribute-delete' pk=attribute.pk %}">
+          <a class="btn-flat waves-effect modal-trigger-custom" href="#base-modal" data-href="{% url 'dashboard:attribute-delete' pk=attribute.pk %}">
             {% trans "Remove attribute" context "Attribute detail action" %}
           </a>
         </div>
@@ -59,7 +59,7 @@
           <span class="card-title">{% trans "Attribute values" %}</span>
         </div>
         <div class="data-table-header-action">
-          <a href="{% url 'dashboard:product-attribute-value-add' attribute_pk=attribute.pk %}" class="btn-flat waves-effect">
+          <a href="{% url 'dashboard:attribute-value-add' attribute_pk=attribute.pk %}" class="btn-flat waves-effect">
             {% trans "Add" %}
           </a>
         </div>
@@ -73,7 +73,7 @@
                 <th></th>
               </tr>
             </thead>
-            <tbody class="sortable-items" data-post-url="{% url 'dashboard:product-attribute-values-reorder' attribute_pk=attribute.pk %}" data-post-name="ordered_values">
+            <tbody class="sortable-items" data-post-url="{% url 'dashboard:attribute-values-reorder' attribute_pk=attribute.pk %}" data-post-name="ordered_values">
               {% for value in values %}
                 <tr class="sortable-item" data-id="{{ value.pk }}">
                   <td class="data-table-icon ignore-link sortable__drag-area">
@@ -83,11 +83,11 @@
                     {{ value.name }}
                   </td>
                   <td class="right-align">
-                    <a href="{% url 'dashboard:product-attribute-value-update' attribute_pk=attribute.pk value_pk=value.pk %}" class="btn-flat waves-effect">
-                      {% trans 'Edit' context 'Attribute choice value edit action' %}
+                    <a href="{% url 'dashboard:attribute-value-update' attribute_pk=attribute.pk value_pk=value.pk %}" class="btn-flat waves-effect">
+                      {% trans 'Edit' context 'Attribute value edit action' %}
                     </a>
-                    <a class="btn-flat waves-effect modal-trigger-custom" href="#base-modal" data-href="{% url 'dashboard:product-attribute-value-delete' attribute_pk=attribute.pk value_pk=value.pk %}">
-                      {% trans 'Remove' context 'Attribute choice value edit action' %}
+                    <a class="btn-flat waves-effect modal-trigger-custom" href="#base-modal" data-href="{% url 'dashboard:attribute-value-delete' attribute_pk=attribute.pk value_pk=value.pk %}">
+                      {% trans 'Remove' context 'Attribute value edit action' %}
                     </a>
                   </td>
                 </tr>
diff --git a/templates/dashboard/product/product_attribute/form.html b/templates/dashboard/product/attribute/form.html
similarity index 83%
rename from templates/dashboard/product/product_attribute/form.html
rename to templates/dashboard/product/attribute/form.html
index 2d4cb1b2a34..f61f6e9df0d 100644
--- a/templates/dashboard/product/product_attribute/form.html
+++ b/templates/dashboard/product/attribute/form.html
@@ -17,7 +17,7 @@
 {% block menu_attributes_class %}active{% endblock %}
 
 {% block header_menu %}
-  {% url "dashboard:product-attributes" as url %}
+  {% url "dashboard:attributes" as url %}
   {% include "dashboard/includes/_back_link.html" with url=url %}
 {% endblock %}
 
@@ -25,18 +25,18 @@
 {% block breadcrumbs %}
   <ul class="breadcrumbs breadcrumbs--history">
     <li>
-      <a href="{% url 'dashboard:product-attributes' %}" class="breadcrumbs--ellipsed-item">
+      <a href="{% url 'dashboard:attributes' %}" class="breadcrumbs--ellipsed-item">
         {% trans "Attributes" context "Dashboard attributes list" %}
       </a>
     </li>
     <li class="back-mobile">
-      <a href="{% url 'dashboard:product-attributes' %}">
+      <a href="{% url 'dashboard:attributes' %}">
         <svg data-src="{% static "dashboard/images/arrow-left.svg" %}" fill="#fff" width="20px" height="20px" />
       </a>
     </li>
     {% if attribute.pk %}
     <li>
-      <a href="{% url 'dashboard:product-attribute-details' attribute.pk %}" class="breadcrumbs--ellipsed-item">
+      <a href="{% url 'dashboard:attribute-details' attribute.pk %}" class="breadcrumbs--ellipsed-item">
         {{ attribute }}
       </a>
     </li>
@@ -73,14 +73,14 @@
           </div>
           <div class="card-action right-align">
             {% if attribute.pk %}
-              <a href="{% url 'dashboard:product-attribute-details' attribute.pk %}" class="btn-flat waves-effect">
+              <a href="{% url 'dashboard:attribute-details' attribute.pk %}" class="btn-flat waves-effect">
                 {% trans "Cancel" context "Dashboard cancel action" %}
               </a>
               <button type="submit" class="btn waves-effect">
                 {% trans "Save" context "Dashboard update action" %}
               </button>
             {% else %}
-              <a href="{% url 'dashboard:product-attributes' %}" class="btn-flat waves-effect">
+              <a href="{% url 'dashboard:attributes' %}" class="btn-flat waves-effect">
                 {% trans "Cancel" context "Dashboard cancel action" %}
               </a>
               <button type="submit" class="btn waves-effect">
diff --git a/templates/dashboard/product/product_attribute/list.html b/templates/dashboard/product/attribute/list.html
similarity index 92%
rename from templates/dashboard/product/product_attribute/list.html
rename to templates/dashboard/product/attribute/list.html
index 841d4e08e38..89f80694795 100644
--- a/templates/dashboard/product/product_attribute/list.html
+++ b/templates/dashboard/product/attribute/list.html
@@ -14,7 +14,7 @@
 
 {% block header_extra %}
   <div class="btn-fab-fixed">
-    <a class="btn-fab-default waves-effect waves-light" href="{% url 'dashboard:product-attribute-add' %}" title="{% trans "Add attribute" context "Attribute list add button text" %}">
+    <a class="btn-fab-default waves-effect waves-light" href="{% url 'dashboard:attribute-add' %}" title="{% trans "Add attribute" context "Attribute list add button text" %}">
       <svg data-src="{% static "dashboard/images/add.svg" %}" />
     </a>
   </div>
@@ -48,7 +48,7 @@
               </thead>
               <tbody>
                 {% for pk, name, values in attributes %}
-                  <tr data-action-go="{% url 'dashboard:product-attribute-details' pk=pk %}">
+                  <tr data-action-go="{% url 'dashboard:attribute-details' pk=pk %}">
                     <td>
                       {{ name }}
                     </td>
diff --git a/templates/dashboard/product/product_attribute/modal/attribute_confirm_delete.html b/templates/dashboard/product/attribute/modal/attribute_confirm_delete.html
similarity index 91%
rename from templates/dashboard/product/product_attribute/modal/attribute_confirm_delete.html
rename to templates/dashboard/product/attribute/modal/attribute_confirm_delete.html
index 4e0d05f036e..d4517ff7632 100644
--- a/templates/dashboard/product/product_attribute/modal/attribute_confirm_delete.html
+++ b/templates/dashboard/product/attribute/modal/attribute_confirm_delete.html
@@ -5,7 +5,7 @@
 {% block form_class %}{% endblock %}
 
 {% block action_url %}
-{% url "dashboard:product-attribute-delete" pk=attribute.pk %}
+{% url "dashboard:attribute-delete" pk=attribute.pk %}
 {% endblock %}
 
 {% block title %}
diff --git a/templates/dashboard/product/product_attribute/values/form.html b/templates/dashboard/product/attribute/values/form.html
similarity index 85%
rename from templates/dashboard/product/product_attribute/values/form.html
rename to templates/dashboard/product/attribute/values/form.html
index 0384d8d55e9..7016478fe16 100644
--- a/templates/dashboard/product/product_attribute/values/form.html
+++ b/templates/dashboard/product/attribute/values/form.html
@@ -17,7 +17,7 @@
 {% block menu_attributes_class %}active{% endblock %}
 
 {% block header_menu %}
-  {% url "dashboard:product-attributes" as url %}
+  {% url "dashboard:attributes" as url %}
   {% include "dashboard/includes/_back_link.html" with url=url %}
 {% endblock %}
 
@@ -25,18 +25,18 @@
 {% block breadcrumbs %}
   <ul class="breadcrumbs breadcrumbs--history">
     <li>
-      <a href="{% url 'dashboard:product-attributes' %}" class="breadcrumbs--ellipsed-item">
+      <a href="{% url 'dashboard:attributes' %}" class="breadcrumbs--ellipsed-item">
         {% trans "Attributes" context "Dashboard attributes list" %}
       </a>
     </li>
     <li class="back-mobile">
-      <a href="{% url 'dashboard:product-attributes' %}">
+      <a href="{% url 'dashboard:attributes' %}">
         <svg data-src="{% static "dashboard/images/arrow-left.svg" %}" fill="#fff" width="20px" height="20px" />
       </a>
     </li>
     {% if attribute.pk %}
     <li>
-      <a href="{% url 'dashboard:product-attribute-details' attribute.pk %}" class="breadcrumbs--ellipsed-item">
+      <a href="{% url 'dashboard:attribute-details' attribute.pk %}" class="breadcrumbs--ellipsed-item">
         {{ attribute }}
       </a>
     </li>
@@ -74,7 +74,7 @@
             </div>
           </div>
           <div class="card-action right-align">
-            <a href="{% url 'dashboard:product-attribute-details' pk=attribute.pk %}" class="btn-flat waves-effect">
+            <a href="{% url 'dashboard:attribute-details' pk=attribute.pk %}" class="btn-flat waves-effect">
               {% trans "Cancel" context "Dashboard cancel action" %}
             </a>
             {% if value.pk %}
diff --git a/templates/dashboard/product/product_attribute/values/modal/confirm_delete.html b/templates/dashboard/product/attribute/values/modal/confirm_delete.html
similarity index 69%
rename from templates/dashboard/product/product_attribute/values/modal/confirm_delete.html
rename to templates/dashboard/product/attribute/values/modal/confirm_delete.html
index d18837b9b07..3f216f6b81a 100644
--- a/templates/dashboard/product/product_attribute/values/modal/confirm_delete.html
+++ b/templates/dashboard/product/attribute/values/modal/confirm_delete.html
@@ -5,19 +5,19 @@
 {% block form_class %}{% endblock %}
 
 {% block action_url %}
-{% url "dashboard:product-attribute-value-delete" attribute_pk=attribute_pk value_pk=value.pk %}
+{% url "dashboard:attribute-value-delete" attribute_pk=attribute_pk value_pk=value.pk %}
 {% endblock %}
 
 {% block title %}
 {% blocktrans trimmed context "Modal delete attribute text" %}
-Delete attribute choice value {{ value }}
+Delete attribute value {{ value }}
 {% endblocktrans %}
 {% endblock title %}
 
 {% block content %}
   <div class="col s12">
     {% blocktrans trimmed context "Modal delete attribute text" %}
-      Are you sure you want to remove attribute choice value <strong>{{ value }}</strong>?
+      Are you sure you want to remove attribute value <strong>{{ value }}</strong>?
     {% endblocktrans %}
   </div>
 {% endblock content %}
diff --git a/templates/dashboard/product/product_attribute/zero_page.html b/templates/dashboard/product/attribute/zero_page.html
similarity index 100%
rename from templates/dashboard/product/product_attribute/zero_page.html
rename to templates/dashboard/product/attribute/zero_page.html
diff --git a/templates/dashboard/shipping/methods/_shipping_methods_table.html b/templates/dashboard/shipping/methods/_shipping_methods_table.html
index 62e2efbb63c..daab08401b8 100644
--- a/templates/dashboard/shipping/methods/_shipping_methods_table.html
+++ b/templates/dashboard/shipping/methods/_shipping_methods_table.html
@@ -36,10 +36,10 @@
               <td>{% price shipping.price %}</td>
               <td class="right-align">
                 <a href="{% url 'dashboard:shipping-method-edit' shipping_zone_pk=shipping_zone.pk shipping_method_pk=shipping.pk %}" class="btn-flat waves-effect">
-                  {% trans 'Edit' context 'Attribute choice value edit action' %}
+                  {% trans 'Edit' context 'Attribute value edit action' %}
                 </a>
                 <a class="btn-flat waves-effect modal-trigger-custom" href="#base-modal" data-href="{% url 'dashboard:shipping-method-delete' shipping_zone_pk=shipping_zone.pk shipping_method_pk=shipping.pk %}">
-                  {% trans 'Remove' context 'Attribute choice value remove action' %}
+                  {% trans 'Remove' context 'Attribute value remove action' %}
                 </a>
               </td>
             </tr>
diff --git a/templates/dashboard/sites/authorization_keys/form.html b/templates/dashboard/sites/authorization_keys/form.html
index f3cffd16e83..2f3f4bbb57f 100644
--- a/templates/dashboard/sites/authorization_keys/form.html
+++ b/templates/dashboard/sites/authorization_keys/form.html
@@ -30,7 +30,7 @@
       </a>
     </li>
     <li class="back-mobile">
-      <a href="{% url 'dashboard:product-attributes' %}">
+      <a href="{% url 'dashboard:attributes' %}">
         <svg data-src="{% static "dashboard/images/arrow-left.svg" %}" fill="#fff" width="20px" height="20px" />
       </a>
     </li>
diff --git a/tests/api/test_attributes.py b/tests/api/test_attributes.py
index 5ed96742b42..6984d19eabb 100644
--- a/tests/api/test_attributes.py
+++ b/tests/api/test_attributes.py
@@ -1,14 +1,13 @@
 import json
-from unittest.mock import Mock
 
 import graphene
 import pytest
 from django.shortcuts import reverse
 from tests.utils import get_graphql_content
 from saleor.product.models import (
-    Category, ProductAttribute, AttributeChoiceValue)
+    Category, Attribute, AttributeValue)
 from saleor.graphql.product.utils import attributes_to_hstore
-from saleor.graphql.product.types import resolve_attribute_value_type, ProductAttributeValueType
+from saleor.graphql.product.types import resolve_attribute_value_type, AttributeValueType
 
 
 def test_attributes_to_hstore(product, color_attribute):
@@ -26,7 +25,7 @@ def test_attributes_to_hstore(product, color_attribute):
     input_data = [{
         'slug': color_attribute.slug, 'value': 'Space Grey'}]
     ids = attributes_to_hstore(input_data, attrs_qs)
-    new_value = AttributeChoiceValue.objects.get(slug='space-grey')
+    new_value = AttributeValue.objects.get(slug='space-grey')
     assert str(color_attribute.pk) in ids
     assert ids[str(color_attribute.pk)] == str(new_value.pk)
 
@@ -38,7 +37,7 @@ def test_attributes_to_hstore(product, color_attribute):
 
 
 def test_attributes_query(user_api_client, product):
-    attributes = ProductAttribute.objects.prefetch_related('values')
+    attributes = Attribute.objects.prefetch_related('values')
     query = '''
     query {
         attributes {
@@ -88,14 +87,14 @@ def test_attributes_in_category_query(user_api_client, product):
     content = get_graphql_content(response)
     assert 'errors' not in content
     attributes_data = content['data']['attributes']['edges']
-    assert len(attributes_data) == ProductAttribute.objects.count()
+    assert len(attributes_data) == Attribute.objects.count()
 
 
-def test_create_product_attribute(admin_api_client):
+def test_create_attribute(admin_api_client):
     query = """
     mutation createAttribute($name: String!, $slug: String!) {
-        productAttributeCreate(input: {name: $name, slug: $slug}) {
-            productAttribute {
+        attributeCreate(input: {name: $name, slug: $slug}) {
+            attribute {
                 name
                 slug
                 values {
@@ -113,18 +112,18 @@ def test_create_product_attribute(admin_api_client):
         reverse('api'), {'query': query, 'variables': variables})
     content = get_graphql_content(response)
     assert 'errors' not in content
-    data = content['data']['productAttributeCreate']['productAttribute']
+    data = content['data']['attributeCreate']['attribute']
     assert data['name'] == name
     assert data['slug'] == slug
     assert not data['values']
 
 
-def test_update_product_attribute(admin_api_client, color_attribute):
+def test_update_attribute(admin_api_client, color_attribute):
     attribute = color_attribute
     query = """
     mutation updateAttribute($id: ID!, $name: String!, $slug: String!) {
-        productAttributeUpdate(id: $id, input: {name: $name, slug: $slug}) {
-            productAttribute {
+        attributeUpdate(id: $id, input: {name: $name, slug: $slug}) {
+            attribute {
                 name
             }
         }
@@ -132,29 +131,29 @@ def test_update_product_attribute(admin_api_client, color_attribute):
     """
     name = 'Wings name'
     slug = attribute.slug
-    id = graphene.Node.to_global_id('ProductAttribute', attribute.id)
+    id = graphene.Node.to_global_id('Attribute', attribute.id)
     variables = json.dumps({'name': name, 'id': id, 'slug': slug})
     response = admin_api_client.post(
         reverse('api'), {'query': query, 'variables': variables})
     content = get_graphql_content(response)
     attribute.refresh_from_db()
     assert 'errors' not in content
-    data = content['data']['productAttributeUpdate']['productAttribute']
+    data = content['data']['attributeUpdate']['attribute']
     assert data['name'] == name == attribute.name
 
 
-def test_delete_product_attribute(admin_api_client, color_attribute):
+def test_delete_attribute(admin_api_client, color_attribute):
     attribute = color_attribute
     query = """
     mutation deleteAttribute($id: ID!) {
-        productAttributeDelete(id: $id) {
-            productAttribute {
+        attributeDelete(id: $id) {
+            attribute {
                 id
             }
         }
     }
     """
-    id = graphene.Node.to_global_id('ProductAttribute', attribute.id)
+    id = graphene.Node.to_global_id('Attribute', attribute.id)
     variables = json.dumps({'id': id})
     response = admin_api_client.post(
         reverse('api'), {'query': query, 'variables': variables})
@@ -164,13 +163,13 @@ def test_delete_product_attribute(admin_api_client, color_attribute):
         attribute.refresh_from_db()
 
 
-def test_create_attribute_choice_value(admin_api_client, color_attribute):
+def test_create_attribute_value(admin_api_client, color_attribute):
     attribute = color_attribute
     query = """
     mutation createChoice($attribute: ID!, $name: String!, $slug: String!, $value: String!) {
-        attributeChoiceValueCreate(
+        attributeValueCreate(
         input: {attribute: $attribute, name: $name, slug: $slug, value: $value}) {
-            attributeChoiceValue {
+            attributeValue {
                 name
                 slug
                 type
@@ -179,7 +178,7 @@ def test_create_attribute_choice_value(admin_api_client, color_attribute):
         }
     }
     """
-    attribute_id = graphene.Node.to_global_id('ProductAttribute', attribute.id)
+    attribute_id = graphene.Node.to_global_id('Attribute', attribute.id)
     name = 'test name'
     slug = 'test-slug'
     value = 'test-string'
@@ -190,27 +189,27 @@ def test_create_attribute_choice_value(admin_api_client, color_attribute):
     content = get_graphql_content(response)
     assert 'errors' not in content
     data = content[
-        'data']['attributeChoiceValueCreate']['attributeChoiceValue']
+        'data']['attributeValueCreate']['attributeValue']
     assert data['name'] == name
     assert data['slug'] == slug
     assert data['value'] == value
     assert data['type'] == 'STRING'
 
 
-def test_update_attribute_choice_value(admin_api_client, pink_choice_value):
-    value = pink_choice_value
+def test_update_attribute_value(admin_api_client, pink_attribute_value):
+    value = pink_attribute_value
     query = """
     mutation updateChoice($id: ID!, $name: String!, $slug: String!) {
-        attributeChoiceValueUpdate(
+        attributeValueUpdate(
         id: $id, input: {name: $name, slug: $slug}) {
-            attributeChoiceValue {
+            attributeValue {
                 name
                 slug
             }
         }
     }
     """
-    id = graphene.Node.to_global_id('ProductAttributeValue', value.id)
+    id = graphene.Node.to_global_id('AttributeValue', value.id)
     name = 'Crimson'
     slug = value.slug
     variables = json.dumps(
@@ -221,24 +220,25 @@ def test_update_attribute_choice_value(admin_api_client, pink_choice_value):
     assert 'errors' not in content
     value.refresh_from_db()
     data = content[
-        'data']['attributeChoiceValueUpdate']['attributeChoiceValue']
+        'data']['attributeValueUpdate']['attributeValue']
     assert data['name'] == name == value.name
 
 
-def test_delete_attribute_choice_value(admin_api_client, color_attribute, pink_choice_value):
-    value = pink_choice_value
+def test_delete_attribute_value(
+        admin_api_client, color_attribute, pink_attribute_value):
+    value = pink_attribute_value
     value = color_attribute.values.get(name='Red')
     query = """
     mutation updateChoice($id: ID!) {
-        attributeChoiceValueDelete(id: $id) {
-            attributeChoiceValue {
+        attributeValueDelete(id: $id) {
+            attributeValue {
                 name
                 slug
             }
         }
     }
     """
-    id = graphene.Node.to_global_id('ProductAttributeValue', value.id)
+    id = graphene.Node.to_global_id('AttributeValue', value.id)
     variables = json.dumps({'id': id})
     response = admin_api_client.post(
         reverse('api'), {'query': query, 'variables': variables})
@@ -247,29 +247,30 @@ def test_delete_attribute_choice_value(admin_api_client, color_attribute, pink_c
     with pytest.raises(value._meta.model.DoesNotExist):
         value.refresh_from_db()
 
+
 @pytest.mark.parametrize('raw_value, expected_type', [
-    ('#0000', ProductAttributeValueType.COLOR),
-    ('#FF69B4', ProductAttributeValueType.COLOR),
-    ('rgb(255, 0, 0)', ProductAttributeValueType.COLOR),
-    ('hsl(0, 100%, 50%)', ProductAttributeValueType.COLOR),
-    ('hsla(120,  60%, 70%, 0.3)', ProductAttributeValueType.COLOR),
-    ('rgba(100%, 255, 0, 0)', ProductAttributeValueType.COLOR),
-    ('http://example.com', ProductAttributeValueType.URL),
-    ('https://example.com', ProductAttributeValueType.URL),
-    ('ftp://example.com', ProductAttributeValueType.URL),
-    ('example.com', ProductAttributeValueType.STRING),
-    ('Foo', ProductAttributeValueType.STRING),
-    ('linear-gradient(red, yellow)', ProductAttributeValueType.GRADIENT),
-    ('radial-gradient(#0000, yellow)', ProductAttributeValueType.GRADIENT),
+    ('#0000', AttributeValueType.COLOR),
+    ('#FF69B4', AttributeValueType.COLOR),
+    ('rgb(255, 0, 0)', AttributeValueType.COLOR),
+    ('hsl(0, 100%, 50%)', AttributeValueType.COLOR),
+    ('hsla(120,  60%, 70%, 0.3)', AttributeValueType.COLOR),
+    ('rgba(100%, 255, 0, 0)', AttributeValueType.COLOR),
+    ('http://example.com', AttributeValueType.URL),
+    ('https://example.com', AttributeValueType.URL),
+    ('ftp://example.com', AttributeValueType.URL),
+    ('example.com', AttributeValueType.STRING),
+    ('Foo', AttributeValueType.STRING),
+    ('linear-gradient(red, yellow)', AttributeValueType.GRADIENT),
+    ('radial-gradient(#0000, yellow)', AttributeValueType.GRADIENT),
 ])
 def test_resolve_attribute_value_type(raw_value, expected_type):
     assert resolve_attribute_value_type(raw_value) == expected_type
 
 
 def test_query_attribute_values(
-        color_attribute, pink_choice_value, user_api_client):
+        color_attribute, pink_attribute_value, user_api_client):
     attribute_id = graphene.Node.to_global_id(
-        'ProductAttribute', color_attribute.id)
+        'Attribute', color_attribute.id)
     query = """
     query getAttribute($id: ID!) {
         attributes(id: $id) {
@@ -294,9 +295,8 @@ def test_query_attribute_values(
     assert 'errors' not in content
     data = content['data']['attributes']['edges'][0]['node']
     values = data['values']
-    pink = [v for v in values if v['name'] == pink_choice_value.name]
+    pink = [v for v in values if v['name'] == pink_attribute_value.name]
     assert len(pink) == 1
     pink = pink[0]
     assert pink['value'] == '#FF69B4'
     assert pink['type'] == 'COLOR'
-
diff --git a/tests/api/test_graphql.py b/tests/api/test_graphql.py
index 96392eccb20..bd4bb9b91ed 100644
--- a/tests/api/test_graphql.py
+++ b/tests/api/test_graphql.py
@@ -162,7 +162,7 @@ def test_real_query(user_api_client, product):
         __typename
     }
 
-    fragment ProductFiltersFragmentQuery on ProductAttribute {
+    fragment ProductFiltersFragmentQuery on Attribute {
         id
         name
         slug
diff --git a/tests/api/test_product.py b/tests/api/test_product.py
index 1a1d6dcf839..300b1008125 100644
--- a/tests/api/test_product.py
+++ b/tests/api/test_product.py
@@ -660,11 +660,11 @@ def test_product_type_create_mutation(admin_api_client, product_type):
     require_shipping = True
     product_attributes = product_type.product_attributes.all()
     product_attributes_ids = [
-        graphene.Node.to_global_id('ProductAttribute', att.id) for att in
+        graphene.Node.to_global_id('Attribute', att.id) for att in
         product_attributes]
     variant_attributes = product_type.variant_attributes.all()
     variant_attributes_ids = [
-        graphene.Node.to_global_id('ProductAttribute', att.id) for att in
+        graphene.Node.to_global_id('Attribute', att.id) for att in
         variant_attributes]
 
     variables = json.dumps({
@@ -690,6 +690,7 @@ def test_product_type_create_mutation(admin_api_client, product_type):
     new_instance = ProductType.objects.latest('pk')
     assert new_instance.tax_rate == 'standard'
 
+
 def test_product_type_update_mutation(admin_api_client, product_type):
     query = """
     mutation updateProductType(
@@ -731,7 +732,7 @@ def test_product_type_update_mutation(admin_api_client, product_type):
     # but do not change variant attributes
     product_attributes = []
     product_attributes_ids = [
-        graphene.Node.to_global_id('ProductAttribute', att.id) for att in
+        graphene.Node.to_global_id('Attribute', att.id) for att in
         product_attributes]
     variant_attributes = product_type.variant_attributes.all()
 
@@ -1220,7 +1221,7 @@ def test_product_type_update_changes_variant_name(
 
     variant_attributes = product_type.variant_attributes.all()
     variant_attributes_ids = [
-        graphene.Node.to_global_id('ProductAttribute', att.id) for att in
+        graphene.Node.to_global_id('Attribute', att.id) for att in
         variant_attributes]
     variables = json.dumps({
         'id': product_type_id,
diff --git a/tests/conftest.py b/tests/conftest.py
index 78781254714..6b24e4083d5 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -31,8 +31,8 @@
 from saleor.order.utils import recalculate_order
 from saleor.page.models import Page
 from saleor.product.models import (
-    AttributeChoiceValue, Category, Collection, Product, ProductAttribute,
-    ProductAttributeTranslation, ProductImage, ProductTranslation, ProductType,
+    AttributeValue, Category, Collection, Product, Attribute,
+    AttributeTranslation, ProductImage, ProductTranslation, ProductType,
     ProductVariant)
 from saleor.shipping.models import (
     ShippingMethod, ShippingMethodType, ShippingZone)
@@ -243,28 +243,28 @@ def shipping_method(shipping_zone):
 
 @pytest.fixture
 def color_attribute(db):  # pylint: disable=W0613
-    attribute = ProductAttribute.objects.create(
+    attribute = Attribute.objects.create(
         slug='color', name='Color')
-    AttributeChoiceValue.objects.create(
+    AttributeValue.objects.create(
         attribute=attribute, name='Red', slug='red')
-    AttributeChoiceValue.objects.create(
+    AttributeValue.objects.create(
         attribute=attribute, name='Blue', slug='blue')
     return attribute
 
 
 @pytest.fixture
-def pink_choice_value(color_attribute):  # pylint: disable=W0613
-    value = AttributeChoiceValue.objects.create(
+def pink_attribute_value(color_attribute):  # pylint: disable=W0613
+    value = AttributeValue.objects.create(
         slug='pink', name='Pink', attribute=color_attribute, value='#FF69B4')
     return value
 
 
 @pytest.fixture
 def size_attribute(db):  # pylint: disable=W0613
-    attribute = ProductAttribute.objects.create(slug='size', name='Size')
-    AttributeChoiceValue.objects.create(
+    attribute = Attribute.objects.create(slug='size', name='Size')
+    AttributeValue.objects.create(
         attribute=attribute, name='Small', slug='small')
-    AttributeChoiceValue.objects.create(
+    AttributeValue.objects.create(
         attribute=attribute, name='Big', slug='big')
     return attribute
 
@@ -708,16 +708,16 @@ def vatlayer(db, settings, tax_rates, taxes):
 @pytest.fixture
 def translated_variant_fr(product):
     attribute = product.product_type.variant_attributes.first()
-    return ProductAttributeTranslation.objects.create(
-        language_code='fr', product_attribute=attribute,
+    return AttributeTranslation.objects.create(
+        language_code='fr', attribute=attribute,
         name='Name tranlsated to french')
 
 
 @pytest.fixture
-def translated_product_attribute(product):
+def translated_attribute(product):
     attribute = product.product_type.product_attributes.first()
-    return ProductAttributeTranslation.objects.create(
-        language_code='fr', product_attribute=attribute,
+    return AttributeTranslation.objects.create(
+        language_code='fr', attribute=attribute,
         name='Name tranlsated to french')
 
 
diff --git a/tests/dashboard/test_permissions.py b/tests/dashboard/test_permissions.py
index d03526340ab..68e182a4f18 100644
--- a/tests/dashboard/test_permissions.py
+++ b/tests/dashboard/test_permissions.py
@@ -634,20 +634,20 @@ def test_staff_can_access_product_image_delete(
 def test_staff_with_permissions_can_view_products_attributes_list(
         staff_client, staff_user, permission_manage_products, color_attribute):
     assert not staff_user.has_perm('product.manage_products')
-    response = staff_client.get(reverse('dashboard:product-attributes'))
+    response = staff_client.get(reverse('dashboard:attributes'))
     assert response.status_code == 302
     response = staff_client.get(
         reverse(
-            'dashboard:product-attribute-details', args=[color_attribute.pk]))
+            'dashboard:attribute-details', args=[color_attribute.pk]))
     assert response.status_code == 302
     staff_user.user_permissions.add(permission_manage_products)
     staff_user = User.objects.get(pk=staff_user.pk)
     assert staff_user.has_perm('product.manage_products')
-    response = staff_client.get(reverse('dashboard:product-attributes'))
+    response = staff_client.get(reverse('dashboard:attributes'))
     assert response.status_code == 200
     response = staff_client.get(
         reverse(
-            'dashboard:product-attribute-details', args=[color_attribute.pk]))
+            'dashboard:attribute-details', args=[color_attribute.pk]))
     assert response.status_code == 200
 
 
@@ -656,26 +656,26 @@ def test_staff_with_permissions_can_update_add_and_delete_products_attributes(
     assert not staff_user.has_perm('product.manage_products')
     response = staff_client.get(
         reverse(
-            'dashboard:product-attribute-update', args=[color_attribute.pk]))
+            'dashboard:attribute-update', args=[color_attribute.pk]))
     assert response.status_code == 302
     response = staff_client.get(
         reverse(
-            'dashboard:product-attribute-delete', args=[color_attribute.pk]))
+            'dashboard:attribute-delete', args=[color_attribute.pk]))
     assert response.status_code == 302
-    response = staff_client.get(reverse('dashboard:product-attribute-add'))
+    response = staff_client.get(reverse('dashboard:attribute-add'))
     assert response.status_code == 302
     staff_user.user_permissions.add(permission_manage_products)
     staff_user = User.objects.get(pk=staff_user.pk)
     assert staff_user.has_perm('product.manage_products')
     response = staff_client.get(
         reverse(
-            'dashboard:product-attribute-update', args=[color_attribute.pk]))
+            'dashboard:attribute-update', args=[color_attribute.pk]))
     assert response.status_code == 200
     response = staff_client.get(
         reverse(
-            'dashboard:product-attribute-delete', args=[color_attribute.pk]))
+            'dashboard:attribute-delete', args=[color_attribute.pk]))
     assert response.status_code == 200
-    response = staff_client.get(reverse('dashboard:product-attribute-add'))
+    response = staff_client.get(reverse('dashboard:attribute-add'))
     assert response.status_code == 200
 
 
@@ -683,7 +683,7 @@ def test_staff_can_access_attribute_create(
         staff_client, staff_user, permission_manage_products, color_attribute):
     assert not staff_user.has_perm('product.manage_products')
     url = reverse(
-        'dashboard:product-attribute-value-add',
+        'dashboard:attribute-value-add',
         kwargs={'attribute_pk': color_attribute.pk})
 
     response = staff_client.get(url)
@@ -702,7 +702,7 @@ def test_staff_can_access_attribute_edit(
     value = color_attribute.values.first()
     assert not staff_user.has_perm('product.manage_products')
     url = reverse(
-        'dashboard:product-attribute-value-update',
+        'dashboard:attribute-value-update',
         kwargs={
             'attribute_pk': color_attribute.pk,
             'value_pk': value.pk})
@@ -723,7 +723,7 @@ def test_staff_can_access_attribute_delete(
     value = color_attribute.values.first()
     assert not staff_user.has_perm('product.manage_products')
     url = reverse(
-        'dashboard:product-attribute-value-delete',
+        'dashboard:attribute-value-delete',
         kwargs={
             'attribute_pk': color_attribute.pk,
             'value_pk': value.pk})
diff --git a/tests/dashboard/test_product.py b/tests/dashboard/test_product.py
index 9bbb3144552..1771050084a 100644
--- a/tests/dashboard/test_product.py
+++ b/tests/dashboard/test_product.py
@@ -12,7 +12,7 @@
 from saleor.dashboard.product.forms import ProductForm, ProductVariantForm
 from saleor.product.forms import VariantChoiceField
 from saleor.product.models import (
-    AttributeChoiceValue, Collection, Product, ProductAttribute, ProductImage,
+    AttributeValue, Collection, Product, Attribute, ProductImage,
     ProductType, ProductVariant)
 
 from ..utils import create_image
@@ -765,7 +765,7 @@ def test_view_ajax_upload_image(monkeypatch, admin_client, product_with_image):
 
 
 def test_view_attribute_list(db, admin_client, color_attribute):
-    url = reverse('dashboard:product-attributes')
+    url = reverse('dashboard:attributes')
 
     response = admin_client.get(url)
 
@@ -780,7 +780,7 @@ def test_view_attribute_list(db, admin_client, color_attribute):
 
 def test_view_attribute_details(admin_client, color_attribute):
     url = reverse(
-        'dashboard:product-attribute-details',
+        'dashboard:attribute-details',
         kwargs={'pk': color_attribute.pk})
 
     response = admin_client.get(url)
@@ -790,9 +790,9 @@ def test_view_attribute_details(admin_client, color_attribute):
 
 
 def test_view_attribute_details_no_choices(admin_client):
-    attribute = ProductAttribute.objects.create(slug='size', name='Size')
+    attribute = Attribute.objects.create(slug='size', name='Size')
     url = reverse(
-        'dashboard:product-attribute-details', kwargs={'pk': attribute.pk})
+        'dashboard:attribute-details', kwargs={'pk': attribute.pk})
 
     response = admin_client.get(url)
 
@@ -801,35 +801,35 @@ def test_view_attribute_details_no_choices(admin_client):
 
 
 def test_view_attribute_create(admin_client, color_attribute):
-    url = reverse('dashboard:product-attribute-add')
+    url = reverse('dashboard:attribute-add')
     data = {'name': 'test', 'slug': 'test'}
 
     response = admin_client.post(url, data, follow=True)
 
     assert response.status_code == 200
-    assert ProductAttribute.objects.count() == 2
+    assert Attribute.objects.count() == 2
 
 
 def test_view_attribute_create_not_valid(admin_client, color_attribute):
-    url = reverse('dashboard:product-attribute-add')
+    url = reverse('dashboard:attribute-add')
     data = {}
 
     response = admin_client.post(url, data, follow=True)
 
     assert response.status_code == 200
-    assert ProductAttribute.objects.count() == 1
+    assert Attribute.objects.count() == 1
 
 
 def test_view_attribute_edit(color_attribute, admin_client):
     url = reverse(
-        'dashboard:product-attribute-update',
+        'dashboard:attribute-update',
         kwargs={'pk': color_attribute.pk})
     data = {'name': 'new_name', 'slug': 'new_slug'}
 
     response = admin_client.post(url, data, follow=True)
 
     assert response.status_code == 200
-    assert ProductAttribute.objects.count() == 1
+    assert Attribute.objects.count() == 1
     color_attribute.refresh_from_db()
     assert color_attribute.name == 'new_name'
     assert color_attribute.slug == 'new_slug'
@@ -837,98 +837,98 @@ def test_view_attribute_edit(color_attribute, admin_client):
 
 def test_view_attribute_delete(admin_client, color_attribute):
     url = reverse(
-        'dashboard:product-attribute-delete',
+        'dashboard:attribute-delete',
         kwargs={'pk': color_attribute.pk})
 
     response = admin_client.post(url)
 
     assert response.status_code == 302
-    assert not ProductAttribute.objects.filter(pk=color_attribute.pk).exists()
+    assert not Attribute.objects.filter(pk=color_attribute.pk).exists()
 
 
 def test_view_attribute_not_deleted_before_confirmation(
         admin_client, color_attribute):
     url = reverse(
-        'dashboard:product-attribute-delete',
+        'dashboard:attribute-delete',
         kwargs={'pk': color_attribute.pk})
 
     response = admin_client.get(url)
 
     assert response.status_code == 200
-    assert ProductAttribute.objects.filter(pk=color_attribute.pk)
+    assert Attribute.objects.filter(pk=color_attribute.pk)
 
 
-def test_view_attribute_choice_value_create(color_attribute, admin_client):
-    values = AttributeChoiceValue.objects.filter(attribute=color_attribute.pk)
+def test_view_attribute_value_create(color_attribute, admin_client):
+    values = AttributeValue.objects.filter(attribute=color_attribute.pk)
     assert values.count() == 2
     url = reverse(
-        'dashboard:product-attribute-value-add',
+        'dashboard:attribute-value-add',
         kwargs={'attribute_pk': color_attribute.pk})
     data = {'name': 'Pink', 'attribute': color_attribute.pk}
 
     response = admin_client.post(url, data, follow=True)
 
     assert response.status_code == 200
-    values = AttributeChoiceValue.objects.filter(attribute=color_attribute.pk)
+    values = AttributeValue.objects.filter(attribute=color_attribute.pk)
     assert values.count() == 3
 
 
-def test_view_attribute_choice_value_create_invalid(
+def test_view_attribute_value_create_invalid(
         color_attribute, admin_client):
-    values = AttributeChoiceValue.objects.filter(attribute=color_attribute.pk)
+    values = AttributeValue.objects.filter(attribute=color_attribute.pk)
     assert values.count() == 2
     url = reverse(
-        'dashboard:product-attribute-value-add',
+        'dashboard:attribute-value-add',
         kwargs={'attribute_pk': color_attribute.pk})
     data = {}
 
     response = admin_client.post(url, data, follow=True)
 
     assert response.status_code == 200
-    values = AttributeChoiceValue.objects.filter(attribute=color_attribute.pk)
+    values = AttributeValue.objects.filter(attribute=color_attribute.pk)
     assert values.count() == 2
 
 
-def test_view_attribute_choice_value_edit(color_attribute, admin_client):
-    values = AttributeChoiceValue.objects.filter(attribute=color_attribute.pk)
+def test_view_attribute_value_edit(color_attribute, admin_client):
+    values = AttributeValue.objects.filter(attribute=color_attribute.pk)
     assert values.count() == 2
     url = reverse(
-        'dashboard:product-attribute-value-update',
+        'dashboard:attribute-value-update',
         kwargs={'attribute_pk': color_attribute.pk, 'value_pk': values[0].pk})
     data = {'name': 'Pink', 'attribute': color_attribute.pk}
 
     response = admin_client.post(url, data, follow=True)
 
     assert response.status_code == 200
-    values = AttributeChoiceValue.objects.filter(
+    values = AttributeValue.objects.filter(
         attribute=color_attribute.pk, name='Pink')
     assert len(values) == 1
     assert values[0].name == 'Pink'
 
 
-def test_view_attribute_choice_value_delete(color_attribute, admin_client):
-    values = AttributeChoiceValue.objects.filter(attribute=color_attribute.pk)
+def test_view_attribute_value_delete(color_attribute, admin_client):
+    values = AttributeValue.objects.filter(attribute=color_attribute.pk)
     assert values.count() == 2
     deleted_value = values[0]
     url = reverse(
-        'dashboard:product-attribute-value-delete',
+        'dashboard:attribute-value-delete',
         kwargs={
             'attribute_pk': color_attribute.pk, 'value_pk': deleted_value.pk})
 
     response = admin_client.post(url, follow=True)
 
     assert response.status_code == 200
-    values = AttributeChoiceValue.objects.filter(attribute=color_attribute.pk)
+    values = AttributeValue.objects.filter(attribute=color_attribute.pk)
     assert len(values) == 1
     assert deleted_value not in values
 
 
-def test_view_ajax_reorder_attribute_choice_values(
+def test_view_ajax_reorder_attribute_values(
         admin_client, color_attribute):
     order_before = [val.pk for val in color_attribute.values.all()]
     ordered_values = list(reversed(order_before))
     url = reverse(
-        'dashboard:product-attribute-values-reorder',
+        'dashboard:attribute-values-reorder',
         kwargs={'attribute_pk': color_attribute.pk})
     data = {'ordered_values': ordered_values}
     response = admin_client.post(
@@ -938,12 +938,12 @@ def test_view_ajax_reorder_attribute_choice_values(
     assert order_after == ordered_values
 
 
-def test_view_ajax_reorder_attribute_choice_values_invalid(
+def test_view_ajax_reorder_attribute_values_invalid(
         admin_client, color_attribute):
     order_before = [val.pk for val in color_attribute.values.all()]
     ordered_values = list(reversed(order_before)).append(3)
     url = reverse(
-        'dashboard:product-attribute-values-reorder',
+        'dashboard:attribute-values-reorder',
         kwargs={'attribute_pk': color_attribute.pk})
     data = {'ordered_values': ordered_values}
     response = admin_client.post(
@@ -955,7 +955,7 @@ def test_view_ajax_reorder_attribute_choice_values_invalid(
 
 
 def test_get_formfield_name_with_unicode_characters(db):
-    text_attribute = ProductAttribute.objects.create(
+    text_attribute = Attribute.objects.create(
         slug='ąęαβδηθλμπ', name='ąęαβδηθλμπ')
     assert text_attribute.get_formfield_name() == 'attribute-ąęαβδηθλμπ'
 
@@ -989,7 +989,7 @@ def test_hide_field_in_variant_choice_field_form():
 
 def test_product_form_change_attributes(db, product, color_attribute):
     product_type = product.product_type
-    text_attribute = ProductAttribute.objects.create(
+    text_attribute = Attribute.objects.create(
         slug='author', name='Author')
     product_type.product_attributes.add(text_attribute)
     color_value = color_attribute.values.first()
@@ -1009,7 +1009,7 @@ def test_product_form_change_attributes(db, product, color_attribute):
     assert product.attributes[str(color_attribute.pk)] == str(color_value.pk)
 
     # Check that new attribute was created for author
-    author_value = AttributeChoiceValue.objects.get(name=new_author)
+    author_value = AttributeValue.objects.get(name=new_author)
     assert product.attributes[str(text_attribute.pk)] == str(author_value.pk)
 
 
diff --git a/tests/test_data_feeds.py b/tests/test_data_feeds.py
index d1a99d965f8..64eb9b346d2 100644
--- a/tests/test_data_feeds.py
+++ b/tests/test_data_feeds.py
@@ -6,7 +6,7 @@
 
 from saleor.data_feeds.google_merchant import (
     get_feed_items, item_attributes, item_google_product_category, write_feed)
-from saleor.product.models import AttributeChoiceValue, Category
+from saleor.product.models import AttributeValue, Category
 
 
 def test_saleor_feed_items(product, site_settings):
@@ -19,7 +19,7 @@ def test_saleor_feed_items(product, site_settings):
     attributes_dict = {}
     current_site = site_settings.site
     attribute_values_dict = {smart_text(a.pk): smart_text(a) for a
-                             in AttributeChoiceValue.objects.all()}
+                             in AttributeValue.objects.all()}
     attributes = item_attributes(items[0], categories, category_paths,
                                  current_site, discounts, attributes_dict,
                                  attribute_values_dict)
diff --git a/tests/test_product.py b/tests/test_product.py
index e1d313a6259..c903b80d3e3 100644
--- a/tests/test_product.py
+++ b/tests/test_product.py
@@ -640,11 +640,11 @@ def test_variant_picker_data_with_translations(
 
 
 def test_get_product_attributes_data_translation(
-        product, settings, translated_product_attribute):
+        product, settings, translated_attribute):
     settings.LANGUAGE_CODE = 'fr'
     attributes_data = get_product_attributes_data(product)
     attributes_keys = [attr.name for attr in attributes_data.keys()]
-    assert translated_product_attribute.name in attributes_keys
+    assert translated_attribute.name in attributes_keys
 
 
 def test_homepage_collection_render(
diff --git a/tests/test_product_attributes.py b/tests/test_product_attributes.py
index 216bab1722f..4345093b0f0 100644
--- a/tests/test_product_attributes.py
+++ b/tests/test_product_attributes.py
@@ -1,7 +1,7 @@
 import pytest
 
 from saleor.product.models import (
-    AttributeChoiceValue, Product, ProductAttribute)
+    AttributeValue, Product, Attribute)
 from saleor.product.utils.attributes import (
     generate_name_from_values, get_attributes_display_map,
     get_name_from_attributes)
@@ -51,13 +51,13 @@ def test_get_name_from_attributes_no_attributes(product_with_no_attributes):
 
 
 def test_generate_name_from_values():
-    attribute = ProductAttribute.objects.create(
+    attribute = Attribute.objects.create(
         slug='color', name='Color')
-    red = AttributeChoiceValue.objects.create(
+    red = AttributeValue.objects.create(
         attribute=attribute, name='Red', slug='red')
-    blue = AttributeChoiceValue.objects.create(
+    blue = AttributeValue.objects.create(
         attribute=attribute, name='Blue', slug='blue')
-    yellow = AttributeChoiceValue.objects.create(
+    yellow = AttributeValue.objects.create(
         attribute=attribute, name='Yellow', slug='yellow')
     values = {'3': red, '2': blue, '1': yellow}
     name = generate_name_from_values(values)
diff --git a/tests/test_translation.py b/tests/test_translation.py
index 9b9b0d0e7e8..d1194a86270 100644
--- a/tests/test_translation.py
+++ b/tests/test_translation.py
@@ -1,8 +1,8 @@
 import pytest
 
 from saleor.product.models import (
-    AttributeChoiceValueTranslation, CategoryTranslation,
-    CollectionTranslation, ProductAttributeTranslation, ProductTranslation,
+    AttributeValueTranslation, CategoryTranslation,
+    CollectionTranslation, AttributeTranslation, ProductTranslation,
     ProductVariantTranslation)
 from saleor.shipping.models import ShippingMethodTranslation
 
@@ -15,10 +15,10 @@ def product_translation_pl(product):
 
 
 @pytest.fixture
-def attribute_choice_translation_fr(translated_product_attribute):
-    value = translated_product_attribute.product_attribute.values.first()
-    return AttributeChoiceValueTranslation.objects.create(
-        language_code='fr', attribute_choice_value=value,
+def attribute_value_translation_fr(translated_attribute):
+    value = translated_attribute.attribute.values.first()
+    return AttributeValueTranslation.objects.create(
+        language_code='fr', attribute_value=value,
         name='French name')
 
 
@@ -98,17 +98,17 @@ def test_product_variant_translation(settings, variant):
     assert variant.translated.name == french_name
 
 
-def test_product_attribute_translation(settings, color_attribute):
-    ProductAttributeTranslation.objects.create(
-        language_code='fr', product_attribute=color_attribute,
+def test_attribute_translation(settings, color_attribute):
+    AttributeTranslation.objects.create(
+        language_code='fr', attribute=color_attribute,
         name='French name')
     assert not color_attribute.translated.name == 'French name'
     settings.LANGUAGE_CODE = 'fr'
     assert color_attribute.translated.name == 'French name'
 
 
-def test_attribute_choice_value_translation(
-        settings, product, attribute_choice_translation_fr):
+def test_attribute_value_translation(
+        settings, product, attribute_value_translation_fr):
     attribute = product.product_type.product_attributes.first().values.first()
     assert not attribute.translated.name == 'French name'
     settings.LANGUAGE_CODE = 'fr'


Code review comments:
diff_hunk: @@ -24,93 +24,93 @@ class AttributeChoiceValueInput(graphene.InputObjectType):
         required=True, description='Real value eg. HEX color.')
 
 
-class AttributeChoiceValueUpdateInput(graphene.InputObjectType):
+class AttributeValueUpdateInput(graphene.InputObjectType):
     slug = graphene.String(
         required=True, description='Internal name.')
     name = graphene.String(
         required=True, description='Name displayed in the interface.')
 
 
-class ProductAttributeCreate(ModelMutation):
+class AttributeCreate(ModelMutation):
     class Arguments:
-        input = ProductAttributesInput(
+        input = AttributesInput(
             required=True,
-            description='Fields required to create a product attribute.')
+            description='Fields required to create an attribute.')
 
     class Meta:
-        description = 'Creates a product attribute.'
-        model = models.ProductAttribute
+        description = 'Creates an attribute.'
+        model = models.Attribute
 
     @classmethod
     def user_is_allowed(cls, user, input):
         return user.has_perm('product.manage_products')
 
 
-class ProductAttributeUpdate(ProductAttributeCreate):
+class AttributeUpdate(AttributeCreate):
     class Arguments:
         id = graphene.ID(
-            required=True, description='ID of a product attribute to update.')
-        input = ProductAttributesInput(
+            required=True, description='ID of an attribute to update.')
+        input = AttributesInput(
             required=True,
-            description='Fields required to update a product attribute.')
+            description='Fields required to update an attribute.')
 
     class Meta:
-        description = 'Updates a product attribute.'
-        model = models.ProductAttribute
+        description = 'Updates anattribute.'
path: saleor/graphql/product/mutations/attributes.py
text: @user1:
Typo: anattribute